sh4.c

Go to the documentation of this file.
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 /* -------- eval.c -------- */
00012 /* #include "sh.h" */
00013 /* #include "word.h" */
00014 
00015 /*
00016  * ${}
00017  * `command`
00018  * blank interpretation
00019  * quoting
00020  * glob
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  * Make the exported environment from the exported
00073  * names in the dictionary. Keyword assignments
00074  * will already have been done.
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  * Blank interpretation and quoting
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  * Get characters, substituting for ` and $
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  * Prepare to generate the string returned by ${} substitution.
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                         /* currently this does not distinguish $* and $@ */
00298                         /* should check dollar */
00299                         e.linep = s;
00300                         PUSHIO(awordlist, dolv+1, dolchar);
00301                         return(0);
00302                 } else {        /* trap the nasty ${=} */
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  * Run the command in `...` and read its output.
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         /* allow trapped signals */
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);      /* free old space */
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 /* -------- glob.c -------- */
00424 /* #include "sh.h" */
00425 
00426 /*
00427  * glob
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++) { /* for each argument */
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  * generate a pathname as below.
00543  * start..end1 / middle end
00544  * the slashes come for free
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 /* -------- word.c -------- */
00588 /* #include "sh.h" */
00589 /* #include "word.h" */
00590 
00591 #define NSTART  16      /* default number of words to allow for initially */
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);     /* perhaps should done by caller */
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 }

Generated on Fri Apr 14 22:57:03 2006 for minix by  doxygen 1.4.6