00001 #define Extern extern
00002 #include <sys/types.h>
00003 #include <sys/stat.h>
00004 #include <sys/dir.h>
00005 #include <limits.h>
00006 #include <signal.h>
00007 #include <errno.h>
00008 #include <setjmp.h>
00009 #include "sh.h"
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 _PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
00024 _PROTOTYPE(static char *blank, (int f ));
00025 _PROTOTYPE(static int dollar, (int quoted ));
00026 _PROTOTYPE(static int grave, (int quoted ));
00027 _PROTOTYPE(void globname, (char *we, char *pp ));
00028 _PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
00029 _PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
00030 _PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
00031 _PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
00032 _PROTOTYPE(void glob1, (char *base, char *lim ));
00033 _PROTOTYPE(void glob2, (char *i, char *j ));
00034 _PROTOTYPE(void glob3, (char *i, char *j, char *k ));
00035 _PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
00036
00037 char **
00038 eval(ap, f)
00039 register char **ap;
00040 int f;
00041 {
00042 struct wdblock *wb;
00043 char **wp;
00044 char **wf;
00045 jmp_buf ev;
00046
00047 wp = NULL;
00048 wb = NULL;
00049 wf = NULL;
00050 if (newenv(setjmp(errpt = ev)) == 0) {
00051 while (*ap && isassign(*ap))
00052 expand(*ap++, &wb, f & ~DOGLOB);
00053 if (flag['k']) {
00054 for (wf = ap; *wf; wf++) {
00055 if (isassign(*wf))
00056 expand(*wf, &wb, f & ~DOGLOB);
00057 }
00058 }
00059 for (wb = addword((char *)0, wb); *ap; ap++) {
00060 if (!flag['k'] || !isassign(*ap))
00061 expand(*ap, &wb, f & ~DOKEY);
00062 }
00063 wb = addword((char *)0, wb);
00064 wp = getwords(wb);
00065 quitenv();
00066 } else
00067 gflg = 1;
00068 return(gflg? (char **)NULL: wp);
00069 }
00070
00071
00072
00073
00074
00075
00076 char **
00077 makenv()
00078
00079 {
00080 register struct wdblock *wb;
00081 register struct var *vp;
00082
00083 wb = NULL;
00084 for (vp = vlist; vp; vp = vp->next)
00085 if (vp->status & EXPORT)
00086 wb = addword(vp->name, wb);
00087 wb = addword((char *)0, wb);
00088 return(getwords(wb));
00089 }
00090
00091 char *
00092 evalstr(cp, f)
00093 register char *cp;
00094 int f;
00095 {
00096 struct wdblock *wb;
00097
00098 wb = NULL;
00099 if (expand(cp, &wb, f)) {
00100 if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
00101 cp = "";
00102 DELETE(wb);
00103 } else
00104 cp = NULL;
00105 return(cp);
00106 }
00107
00108 static int
00109 expand(cp, wbp, f)
00110 register char *cp;
00111 register struct wdblock **wbp;
00112 int f;
00113 {
00114 jmp_buf ev;
00115
00116 gflg = 0;
00117 if (cp == NULL)
00118 return(0);
00119 if (!anys("$`'\"", cp) &&
00120 !anys(ifs->value, cp) &&
00121 ((f&DOGLOB)==0 || !anys("[*?", cp))) {
00122 cp = strsave(cp, areanum);
00123 if (f & DOTRIM)
00124 unquote(cp);
00125 *wbp = addword(cp, *wbp);
00126 return(1);
00127 }
00128 if (newenv(setjmp(errpt = ev)) == 0) {
00129 PUSHIO(aword, cp, strchar);
00130 e.iobase = e.iop;
00131 while ((cp = blank(f)) && gflg == 0) {
00132 e.linep = cp;
00133 cp = strsave(cp, areanum);
00134 if ((f&DOGLOB) == 0) {
00135 if (f & DOTRIM)
00136 unquote(cp);
00137 *wbp = addword(cp, *wbp);
00138 } else
00139 *wbp = glob(cp, *wbp);
00140 }
00141 quitenv();
00142 } else
00143 gflg = 1;
00144 return(gflg == 0);
00145 }
00146
00147
00148
00149
00150 static char *
00151 blank(f)
00152 int f;
00153 {
00154 register c, c1;
00155 register char *sp;
00156 int scanequals, foundequals;
00157
00158 sp = e.linep;
00159 scanequals = f & DOKEY;
00160 foundequals = 0;
00161
00162 loop:
00163 switch (c = subgetc('"', foundequals)) {
00164 case 0:
00165 if (sp == e.linep)
00166 return(0);
00167 *e.linep++ = 0;
00168 return(sp);
00169
00170 default:
00171 if (f & DOBLANK && any(c, ifs->value))
00172 goto loop;
00173 break;
00174
00175 case '"':
00176 case '\'':
00177 scanequals = 0;
00178 if (INSUB())
00179 break;
00180 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
00181 if (c == 0)
00182 break;
00183 if (c == '\'' || !any(c, "$`\""))
00184 c |= QUOTE;
00185 *e.linep++ = c;
00186 }
00187 c = 0;
00188 }
00189 unget(c);
00190 if (!letter(c))
00191 scanequals = 0;
00192 for (;;) {
00193 c = subgetc('"', foundequals);
00194 if (c == 0 ||
00195 (f & DOBLANK && any(c, ifs->value)) ||
00196 (!INSUB() && any(c, "\"'"))) {
00197 scanequals = 0;
00198 unget(c);
00199 if (any(c, "\"'"))
00200 goto loop;
00201 break;
00202 }
00203 if (scanequals)
00204 if (c == '=') {
00205 foundequals = 1;
00206 scanequals = 0;
00207 }
00208 else if (!letnum(c))
00209 scanequals = 0;
00210 *e.linep++ = c;
00211 }
00212 *e.linep++ = 0;
00213 return(sp);
00214 }
00215
00216
00217
00218
00219 int
00220 subgetc(ec, quoted)
00221 register char ec;
00222 int quoted;
00223 {
00224 register char c;
00225
00226 again:
00227 c = getc(ec);
00228 if (!INSUB() && ec != '\'') {
00229 if (c == '`') {
00230 if (grave(quoted) == 0)
00231 return(0);
00232 e.iop->task = XGRAVE;
00233 goto again;
00234 }
00235 if (c == '$' && (c = dollar(quoted)) == 0) {
00236 e.iop->task = XDOLL;
00237 goto again;
00238 }
00239 }
00240 return(c);
00241 }
00242
00243
00244
00245
00246 static int
00247 dollar(quoted)
00248 int quoted;
00249 {
00250 int otask;
00251 struct io *oiop;
00252 char *dolp;
00253 register char *s, c, *cp;
00254 struct var *vp;
00255
00256 c = readc();
00257 s = e.linep;
00258 if (c != '{') {
00259 *e.linep++ = c;
00260 if (letter(c)) {
00261 while ((c = readc())!=0 && letnum(c))
00262 if (e.linep < elinep)
00263 *e.linep++ = c;
00264 unget(c);
00265 }
00266 c = 0;
00267 } else {
00268 oiop = e.iop;
00269 otask = e.iop->task;
00270 e.iop->task = XOTHER;
00271 while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
00272 if (e.linep < elinep)
00273 *e.linep++ = c;
00274 if (oiop == e.iop)
00275 e.iop->task = otask;
00276 if (c != '}') {
00277 err("unclosed ${");
00278 gflg++;
00279 return(c);
00280 }
00281 }
00282 if (e.linep >= elinep) {
00283 err("string in ${} too long");
00284 gflg++;
00285 e.linep -= 10;
00286 }
00287 *e.linep = 0;
00288 if (*s)
00289 for (cp = s+1; *cp; cp++)
00290 if (any(*cp, "=-+?")) {
00291 c = *cp;
00292 *cp++ = 0;
00293 break;
00294 }
00295 if (s[1] == 0 && (*s == '*' || *s == '@')) {
00296 if (dolc > 1) {
00297
00298
00299 e.linep = s;
00300 PUSHIO(awordlist, dolv+1, dolchar);
00301 return(0);
00302 } else {
00303 s[0] = '1';
00304 s[1] = 0;
00305 }
00306 }
00307 e.linep = s;
00308 vp = lookup(s);
00309 if ((dolp = vp->value) == null) {
00310 switch (c) {
00311 case '=':
00312 if (digit(*s)) {
00313 err("cannot use ${...=...} with $n");
00314 gflg++;
00315 break;
00316 }
00317 cp = evalstr(strsave(cp, areanum),DOSUB);
00318 setval(vp, cp);
00319 dolp = vp->value;
00320 break;
00321
00322 case '-':
00323 dolp = evalstr(strsave(cp, areanum),DOSUB);
00324 break;
00325
00326 case '?':
00327 if (*cp == 0) {
00328 prs("missing value for ");
00329 err(s);
00330 } else
00331 err(evalstr(strsave(cp, areanum),DOSUB));
00332 gflg++;
00333 break;
00334 }
00335 } else if (c == '+') {
00336 dolp = evalstr(strsave(cp, areanum),DOSUB);
00337 }
00338 if (flag['u'] && dolp == null) {
00339 prs("unset variable: ");
00340 err(s);
00341 gflg++;
00342 }
00343 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
00344 return(0);
00345 }
00346
00347
00348
00349
00350 static int
00351 grave(quoted)
00352 int quoted;
00353 {
00354 int otask;
00355 struct io *oiop;
00356 register char *cp,*s;
00357 register int i,c;
00358 int pf[2];
00359
00360 c = readc();
00361 s = e.linep;
00362 *e.linep++ = c;
00363 oiop = e.iop;
00364 otask = e.iop->task;
00365 e.iop->task = XOTHER;
00366 while ((c = subgetc('\'', 0))!=0 && c!='`')
00367 if (e.linep < elinep)
00368 *e.linep++ = c;
00369 if (oiop == e.iop)
00370 e.iop->task = otask;
00371 if (c != '`') {
00372 err("no closing `");
00373 return(0);
00374 }
00375 if (openpipe(pf) < 0)
00376 return(0);
00377 if ((i = fork()) == -1) {
00378 closepipe(pf);
00379 err("try again");
00380 return(0);
00381 }
00382 if (i != 0) {
00383 e.linep = s;
00384 close(pf[1]);
00385 PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
00386 return(1);
00387 }
00388 *e.linep = 0;
00389
00390 for (i=0; i<=_NSIG; i++)
00391 if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
00392 signal(i, SIG_DFL);
00393 dup2(pf[1], 1);
00394 closepipe(pf);
00395 flag['e'] = 0;
00396 flag['v'] = 0;
00397 flag['n'] = 0;
00398 cp = strsave(e.linep = s, 0);
00399 areanum = 1;
00400 inithere();
00401 freearea(areanum);
00402 e.oenv = NULL;
00403 e.iop = (e.iobase = iostack) - 1;
00404 unquote(cp);
00405 talking = 0;
00406 PUSHIO(aword, cp, nlchar);
00407 onecommand();
00408 exit(1);
00409 }
00410
00411 char *
00412 unquote(as)
00413 register char *as;
00414 {
00415 register char *s;
00416
00417 if ((s = as) != NULL)
00418 while (*s)
00419 *s++ &= ~QUOTE;
00420 return(as);
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430 #define scopy(x) strsave((x), areanum)
00431 #define BLKSIZ 512
00432 #define NDENT ((BLKSIZ+sizeof(struct direct)-1)/sizeof(struct direct))
00433
00434 static struct wdblock *cl, *nl;
00435 static char spcl[] = "[?*";
00436
00437 struct wdblock *
00438 glob(cp, wb)
00439 char *cp;
00440 struct wdblock *wb;
00441 {
00442 register i;
00443 register char *pp;
00444
00445 if (cp == 0)
00446 return(wb);
00447 i = 0;
00448 for (pp = cp; *pp; pp++)
00449 if (any(*pp, spcl))
00450 i++;
00451 else if (!any(*pp & ~QUOTE, spcl))
00452 *pp &= ~QUOTE;
00453 if (i != 0) {
00454 for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
00455 nl = newword(cl->w_nword*2);
00456 for(i=0; i<cl->w_nword; i++) {
00457 for (pp = cl->w_words[i]; *pp; pp++)
00458 if (any(*pp, spcl)) {
00459 globname(cl->w_words[i], pp);
00460 break;
00461 }
00462 if (*pp == '\0')
00463 nl = addword(scopy(cl->w_words[i]), nl);
00464 }
00465 for(i=0; i<cl->w_nword; i++)
00466 DELETE(cl->w_words[i]);
00467 DELETE(cl);
00468 }
00469 for(i=0; i<cl->w_nword; i++)
00470 unquote(cl->w_words[i]);
00471 glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
00472 if (cl->w_nword) {
00473 for (i=0; i<cl->w_nword; i++)
00474 wb = addword(cl->w_words[i], wb);
00475 DELETE(cl);
00476 return(wb);
00477 }
00478 }
00479 wb = addword(unquote(cp), wb);
00480 return(wb);
00481 }
00482
00483 void
00484 globname(we, pp)
00485 char *we;
00486 register char *pp;
00487 {
00488 register char *np, *cp;
00489 char *name, *gp, *dp;
00490 int dn, j, n, k;
00491 struct direct ent[NDENT];
00492 char dname[NAME_MAX+1];
00493 struct stat dbuf;
00494
00495 for (np = we; np != pp; pp--)
00496 if (pp[-1] == '/')
00497 break;
00498 for (dp = cp = space((int)(pp-np)+3); np < pp;)
00499 *cp++ = *np++;
00500 *cp++ = '.';
00501 *cp = '\0';
00502 for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
00503 *cp++ = *np++;
00504 *cp = '\0';
00505 dn = open(dp, 0);
00506 if (dn < 0) {
00507 DELETE(dp);
00508 DELETE(gp);
00509 return;
00510 }
00511 dname[NAME_MAX] = '\0';
00512 while ((n = read(dn, (char *)ent, sizeof(ent))) >= sizeof(*ent)) {
00513 n /= sizeof(*ent);
00514 for (j=0; j<n; j++) {
00515 if (ent[j].d_ino == 0)
00516 continue;
00517 strncpy(dname, ent[j].d_name, NAME_MAX);
00518 if (dname[0] == '.')
00519 if (*gp != '.')
00520 continue;
00521 for(k=0; k<NAME_MAX; k++)
00522 if (any(dname[k], spcl))
00523 dname[k] |= QUOTE;
00524 if (gmatch(dname, gp)) {
00525 name = generate(we, pp, dname, np);
00526 if (*np && !anys(np, spcl)) {
00527 if (stat(name,&dbuf)) {
00528 DELETE(name);
00529 continue;
00530 }
00531 }
00532 nl = addword(name, nl);
00533 }
00534 }
00535 }
00536 close(dn);
00537 DELETE(dp);
00538 DELETE(gp);
00539 }
00540
00541
00542
00543
00544
00545
00546 static char *
00547 generate(start1, end1, middle, end)
00548 char *start1;
00549 register char *end1;
00550 char *middle, *end;
00551 {
00552 char *p;
00553 register char *op, *xp;
00554
00555 p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
00556 for (xp = start1; xp != end1;)
00557 *op++ = *xp++;
00558 for (xp = middle; (*op++ = *xp++) != '\0';)
00559 ;
00560 op--;
00561 for (xp = end; (*op++ = *xp++) != '\0';)
00562 ;
00563 return(p);
00564 }
00565
00566 static int
00567 anyspcl(wb)
00568 register struct wdblock *wb;
00569 {
00570 register i;
00571 register char **wd;
00572
00573 wd = wb->w_words;
00574 for (i=0; i<wb->w_nword; i++)
00575 if (anys(spcl, *wd++))
00576 return(1);
00577 return(0);
00578 }
00579
00580 static int
00581 xstrcmp(p1, p2)
00582 char *p1, *p2;
00583 {
00584 return(strcmp(*(char **)p1, *(char **)p2));
00585 }
00586
00587
00588
00589
00590
00591 #define NSTART 16
00592
00593 struct wdblock *
00594 newword(nw)
00595 register int nw;
00596 {
00597 register struct wdblock *wb;
00598
00599 wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
00600 wb->w_bsize = nw;
00601 wb->w_nword = 0;
00602 return(wb);
00603 }
00604
00605 struct wdblock *
00606 addword(wd, wb)
00607 char *wd;
00608 register struct wdblock *wb;
00609 {
00610 register struct wdblock *wb2;
00611 register nw;
00612
00613 if (wb == NULL)
00614 wb = newword(NSTART);
00615 if ((nw = wb->w_nword) >= wb->w_bsize) {
00616 wb2 = newword(nw * 2);
00617 memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
00618 wb2->w_nword = nw;
00619 DELETE(wb);
00620 wb = wb2;
00621 }
00622 wb->w_words[wb->w_nword++] = wd;
00623 return(wb);
00624 }
00625
00626 char **
00627 getwords(wb)
00628 register struct wdblock *wb;
00629 {
00630 register char **wd;
00631 register nb;
00632
00633 if (wb == NULL)
00634 return((char **)NULL);
00635 if (wb->w_nword == 0) {
00636 DELETE(wb);
00637 return((char **)NULL);
00638 }
00639 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
00640 memcopy((char *)wd, (char *)wb->w_words, nb);
00641 DELETE(wb);
00642 return(wd);
00643 }
00644
00645 _PROTOTYPE(int (*func), (char *, char *));
00646 int globv;
00647
00648 void
00649 glob0(a0, a1, a2, a3)
00650 char *a0;
00651 unsigned a1;
00652 int a2;
00653 _PROTOTYPE(int (*a3), (char *, char *));
00654 {
00655 func = a3;
00656 globv = a2;
00657 glob1(a0, a0 + a1 * a2);
00658 }
00659
00660 void
00661 glob1(base, lim)
00662 char *base, *lim;
00663 {
00664 register char *i, *j;
00665 int v2;
00666 char *lptr, *hptr;
00667 int c;
00668 unsigned n;
00669
00670
00671 v2 = globv;
00672
00673 top:
00674 if ((n=(int)(lim-base)) <= v2)
00675 return;
00676 n = v2 * (n / (2*v2));
00677 hptr = lptr = base+n;
00678 i = base;
00679 j = lim-v2;
00680 for(;;) {
00681 if (i < lptr) {
00682 if ((c = (*func)(i, lptr)) == 0) {
00683 glob2(i, lptr -= v2);
00684 continue;
00685 }
00686 if (c < 0) {
00687 i += v2;
00688 continue;
00689 }
00690 }
00691
00692 begin:
00693 if (j > hptr) {
00694 if ((c = (*func)(hptr, j)) == 0) {
00695 glob2(hptr += v2, j);
00696 goto begin;
00697 }
00698 if (c > 0) {
00699 if (i == lptr) {
00700 glob3(i, hptr += v2, j);
00701 i = lptr += v2;
00702 goto begin;
00703 }
00704 glob2(i, j);
00705 j -= v2;
00706 i += v2;
00707 continue;
00708 }
00709 j -= v2;
00710 goto begin;
00711 }
00712
00713
00714 if (i == lptr) {
00715 if (lptr-base >= lim-hptr) {
00716 glob1(hptr+v2, lim);
00717 lim = lptr;
00718 } else {
00719 glob1(base, lptr);
00720 base = hptr+v2;
00721 }
00722 goto top;
00723 }
00724
00725
00726 glob3(j, lptr -= v2, i);
00727 j = hptr -= v2;
00728 }
00729 }
00730
00731 void
00732 glob2(i, j)
00733 char *i, *j;
00734 {
00735 register char *index1, *index2, c;
00736 int m;
00737
00738 m = globv;
00739 index1 = i;
00740 index2 = j;
00741 do {
00742 c = *index1;
00743 *index1++ = *index2;
00744 *index2++ = c;
00745 } while(--m);
00746 }
00747
00748 void
00749 glob3(i, j, k)
00750 char *i, *j, *k;
00751 {
00752 register char *index1, *index2, *index3;
00753 int c;
00754 int m;
00755
00756 m = globv;
00757 index1 = i;
00758 index2 = j;
00759 index3 = k;
00760 do {
00761 c = *index1;
00762 *index1++ = *index3;
00763 *index3++ = *index2;
00764 *index2++ = c;
00765 } while(--m);
00766 }
00767
00768 char *
00769 memcopy(ato, from, nb)
00770 register char *ato, *from;
00771 register int nb;
00772 {
00773 register char *to;
00774
00775 to = ato;
00776 while (--nb >= 0)
00777 *to++ = *from++;
00778 return(ato);
00779 }