sh3.c

Go to the documentation of this file.
00001 #define Extern extern
00002 #include <sys/types.h>
00003 #include <signal.h>
00004 #include <errno.h>
00005 #include <setjmp.h>
00006 #include <stddef.h>
00007 #include <time.h>
00008 #include <sys/times.h>
00009 #include <sys/stat.h>
00010 #include <sys/wait.h>
00011 #undef NULL
00012 #include "sh.h"
00013 
00014 /* -------- exec.c -------- */
00015 /* #include "sh.h" */
00016 
00017 /*
00018  * execute tree
00019  */
00020 
00021 static  char    *signame[] = {
00022         "Signal 0",
00023         "Hangup",
00024         (char *)NULL,   /* interrupt */
00025         "Quit",
00026         "Illegal instruction",
00027         "Trace/BPT trap",
00028         "Abort",
00029         "EMT trap",
00030         "Floating exception",
00031         "Killed",
00032         "Bus error",
00033         "Memory fault",
00034         "Bad system call",
00035         (char *)NULL,   /* broken pipe */
00036         "Alarm clock",
00037         "Terminated",
00038 };
00039 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
00040 
00041 
00042 _PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ));
00043 _PROTOTYPE(static int parent, (void));
00044 _PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout ));
00045 _PROTOTYPE(static void echo, (char **wp ));
00046 _PROTOTYPE(static struct op **find1case, (struct op *t, char *w ));
00047 _PROTOTYPE(static struct op *findcase, (struct op *t, char *w ));
00048 _PROTOTYPE(static void brkset, (struct brkcon *bc ));
00049 _PROTOTYPE(int dolabel, (void));
00050 _PROTOTYPE(int dochdir, (struct op *t ));
00051 _PROTOTYPE(int doshift, (struct op *t ));
00052 _PROTOTYPE(int dologin, (struct op *t ));
00053 _PROTOTYPE(int doumask, (struct op *t ));
00054 _PROTOTYPE(int doexec, (struct op *t ));
00055 _PROTOTYPE(int dodot, (struct op *t ));
00056 _PROTOTYPE(int dowait, (struct op *t ));
00057 _PROTOTYPE(int doread, (struct op *t ));
00058 _PROTOTYPE(int doeval, (struct op *t ));
00059 _PROTOTYPE(int dotrap, (struct op *t ));
00060 _PROTOTYPE(int getsig, (char *s ));
00061 _PROTOTYPE(void setsig, (int n, void (*f)()));
00062 _PROTOTYPE(int getn, (char *as ));
00063 _PROTOTYPE(int dobreak, (struct op *t ));
00064 _PROTOTYPE(int docontinue, (struct op *t ));
00065 _PROTOTYPE(static int brkcontin, (char *cp, int val ));
00066 _PROTOTYPE(int doexit, (struct op *t ));
00067 _PROTOTYPE(int doexport, (struct op *t ));
00068 _PROTOTYPE(int doreadonly, (struct op *t ));
00069 _PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key));
00070 _PROTOTYPE(static void badid, (char *s ));
00071 _PROTOTYPE(int doset, (struct op *t ));
00072 _PROTOTYPE(void varput, (char *s, int out ));
00073 _PROTOTYPE(int dotimes, (void));
00074 
00075 int
00076 execute(t, pin, pout, act)
00077 register struct op *t;
00078 int *pin, *pout;
00079 int act;
00080 {
00081         register struct op *t1;
00082         int i, pv[2], rv, child, a;
00083         char *cp, **wp, **wp2;
00084         struct var *vp;
00085         struct brkcon bc;
00086 
00087         if (t == NULL)
00088                 return(0);
00089         rv = 0;
00090         a = areanum++;
00091         wp = (wp2 = t->words) != NULL
00092              ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
00093              : NULL;
00094 
00095         switch(t->type) {
00096         case TPAREN:
00097         case TCOM:
00098                 rv = forkexec(t, pin, pout, act, wp, &child);
00099                 if (child) {
00100                         exstat = rv;
00101                         leave();
00102                 }
00103                 break;
00104 
00105         case TPIPE:
00106                 if ((rv = openpipe(pv)) < 0)
00107                         break;
00108                 pv[0] = remap(pv[0]);
00109                 pv[1] = remap(pv[1]);
00110                 (void) execute(t->left, pin, pv, 0);
00111                 rv = execute(t->right, pv, pout, 0);
00112                 break;
00113 
00114         case TLIST:
00115                 (void) execute(t->left, pin, pout, 0);
00116                 rv = execute(t->right, pin, pout, 0);
00117                 break;
00118 
00119         case TASYNC:
00120                 i = parent();
00121                 if (i != 0) {
00122                         if (i != -1) {
00123                                 setval(lookup("!"), putn(i));
00124                                 if (pin != NULL)
00125                                         closepipe(pin);
00126                                 if (talking) {
00127                                         prs(putn(i));
00128                                         prs("\n");
00129                                 }
00130                         } else
00131                                 rv = -1;
00132                         setstatus(rv);
00133                 } else {
00134                         signal(SIGINT, SIG_IGN);
00135                         signal(SIGQUIT, SIG_IGN);
00136                         if (talking)
00137                                 signal(SIGTERM, SIG_DFL);
00138                         talking = 0;
00139                         if (pin == NULL) {
00140                                 close(0);
00141                                 open("/dev/null", 0);
00142                         }
00143                         exit(execute(t->left, pin, pout, FEXEC));
00144                 }
00145                 break;
00146 
00147         case TOR:
00148         case TAND:
00149                 rv = execute(t->left, pin, pout, 0);
00150                 if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
00151                         rv = execute(t1, pin, pout, 0);
00152                 break;
00153 
00154         case TFOR:
00155                 if (wp == NULL) {
00156                         wp = dolv+1;
00157                         if ((i = dolc) < 0)
00158                                 i = 0;
00159                 } else {
00160                         i = -1;
00161                         while (*wp++ != NULL)
00162                                 ;                       
00163                 }
00164                 vp = lookup(t->str);
00165                 while (setjmp(bc.brkpt))
00166                         if (isbreak)
00167                                 goto broken;
00168                 brkset(&bc);
00169                 for (t1 = t->left; i-- && *wp != NULL;) {
00170                         setval(vp, *wp++);
00171                         rv = execute(t1, pin, pout, 0);
00172                 }
00173                 brklist = brklist->nextlev;
00174                 break;
00175 
00176         case TWHILE:
00177         case TUNTIL:
00178                 while (setjmp(bc.brkpt))
00179                         if (isbreak)
00180                                 goto broken;
00181                 brkset(&bc);
00182                 t1 = t->left;
00183                 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
00184                         rv = execute(t->right, pin, pout, 0);
00185                 brklist = brklist->nextlev;
00186                 break;
00187 
00188         case TIF:
00189         case TELIF:
00190                 if (t->right != NULL) {
00191                 rv = !execute(t->left, pin, pout, 0) ?
00192                         execute(t->right->left, pin, pout, 0):
00193                         execute(t->right->right, pin, pout, 0);
00194                 }
00195                 break;
00196 
00197         case TCASE:
00198                 if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
00199                         cp = "";
00200                 if ((t1 = findcase(t->left, cp)) != NULL)
00201                         rv = execute(t1, pin, pout, 0);
00202                 break;
00203 
00204         case TBRACE:
00205 /*
00206                 if (iopp = t->ioact)
00207                         while (*iopp)
00208                                 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
00209                                         rv = -1;
00210                                         break;
00211                                 }
00212 */
00213                 if (rv >= 0 && (t1 = t->left))
00214                         rv = execute(t1, pin, pout, 0);
00215                 break;
00216         }
00217 
00218 broken:
00219         t->words = wp2;
00220         isbreak = 0;
00221         freehere(areanum);
00222         freearea(areanum);
00223         areanum = a;
00224         if (talking && intr) {
00225                 closeall();
00226                 fail();
00227         }
00228         if ((i = trapset) != 0) {
00229                 trapset = 0;
00230                 runtrap(i);
00231         }
00232         return(rv);
00233 }
00234 
00235 static int
00236 forkexec(t, pin, pout, act, wp, pforked)
00237 register struct op *t;
00238 int *pin, *pout;
00239 int act;
00240 char **wp;
00241 int *pforked;
00242 {
00243         int i, rv, (*shcom)();
00244         register int f;
00245         char *cp;
00246         struct ioword **iopp;
00247         int resetsig;
00248         char **owp;
00249 
00250         owp = wp;
00251         resetsig = 0;
00252         *pforked = 0;
00253         shcom = NULL;
00254         rv = -1;        /* system-detected error */
00255         if (t->type == TCOM) {
00256                 while ((cp = *wp++) != NULL)
00257                         ;
00258                 cp = *wp;
00259 
00260                 /* strip all initial assignments */
00261                 /* not correct wrt PATH=yyy command  etc */
00262                 if (flag['x'])
00263                         echo (cp ? wp: owp);
00264                 if (cp == NULL && t->ioact == NULL) {
00265                         while ((cp = *owp++) != NULL && assign(cp, COPYV))
00266                                 ;
00267                         return(setstatus(0));
00268                 }
00269                 else if (cp != NULL)
00270                         shcom = inbuilt(cp);
00271         }
00272         t->words = wp;
00273         f = act;
00274         if (shcom == NULL && (f & FEXEC) == 0) {
00275                 i = parent();
00276                 if (i != 0) {
00277                         if (i == -1)
00278                                 return(rv);
00279                         if (pin != NULL)
00280                                 closepipe(pin);
00281                         return(pout==NULL? setstatus(waitfor(i,0)): 0);
00282                 }
00283                 if (talking) {
00284                         signal(SIGINT, SIG_IGN);
00285                         signal(SIGQUIT, SIG_IGN);
00286                         resetsig = 1;
00287                 }
00288                 talking = 0;
00289                 intr = 0;
00290                 (*pforked)++;
00291                 brklist = 0;
00292                 execflg = 0;
00293         }
00294         if (owp != NULL)
00295                 while ((cp = *owp++) != NULL && assign(cp, COPYV))
00296                         if (shcom == NULL)
00297                                 export(lookup(cp));
00298 #ifdef COMPIPE
00299         if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
00300                 err("piping to/from shell builtins not yet done");
00301                 return(-1);
00302         }
00303 #endif
00304         if (pin != NULL) {
00305                 dup2(pin[0], 0);
00306                 closepipe(pin);
00307         }
00308         if (pout != NULL) {
00309                 dup2(pout[1], 1);
00310                 closepipe(pout);
00311         }
00312         if ((iopp = t->ioact) != NULL) {
00313                 if (shcom != NULL && shcom != doexec) {
00314                         prs(cp);
00315                         err(": cannot redirect shell command");
00316                         return(-1);
00317                 }
00318                 while (*iopp)
00319                         if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
00320                                 return(rv);
00321         }
00322         if (shcom)
00323                 return(setstatus((*shcom)(t)));
00324         /* should use FIOCEXCL */
00325         for (i=FDBASE; i<NOFILE; i++)
00326                 close(i);
00327         if (resetsig) {
00328                 signal(SIGINT, SIG_DFL);
00329                 signal(SIGQUIT, SIG_DFL);
00330         }
00331         if (t->type == TPAREN)
00332                 exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
00333         if (wp[0] == NULL)
00334                 exit(0);
00335         cp = rexecve(wp[0], wp, makenv());
00336         prs(wp[0]); prs(": "); warn(cp);
00337         if (!execflg)
00338                 trap[0] = NULL;
00339         leave();
00340         /* NOTREACHED */
00341 }
00342 
00343 /*
00344  * common actions when creating a new child
00345  */
00346 static int
00347 parent()
00348 {
00349         register int i;
00350 
00351         i = fork();
00352         if (i != 0) {
00353                 if (i == -1)
00354                         warn("try again");
00355         }
00356         return(i);
00357 }
00358 
00359 /*
00360  * 0< 1> are ignored as required
00361  * within pipelines.
00362  */
00363 int
00364 iosetup(iop, pipein, pipeout)
00365 register struct ioword *iop;
00366 int pipein, pipeout;
00367 {
00368         register u;
00369         char *cp, *msg;
00370 
00371         if (iop->io_unit == IODEFAULT)  /* take default */
00372                 iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
00373         if (pipein && iop->io_unit == 0)
00374                 return(0);
00375         if (pipeout && iop->io_unit == 1)
00376                 return(0);
00377         msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
00378         if ((iop->io_flag & IOHERE) == 0) {
00379                 cp = iop->io_name;
00380                 if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
00381                         return(1);
00382         }
00383         if (iop->io_flag & IODUP) {
00384                 if (cp[1] || (!digit(*cp) && *cp != '-')) {
00385                         prs(cp);
00386                         err(": illegal >& argument");
00387                         return(1);
00388                 }
00389                 if (*cp == '-')
00390                         iop->io_flag = IOCLOSE;
00391                 iop->io_flag &= ~(IOREAD|IOWRITE);
00392         }
00393         switch (iop->io_flag) {
00394         case IOREAD:
00395                 u = open(cp, 0);
00396                 break;
00397 
00398         case IOHERE:
00399         case IOHERE|IOXHERE:
00400                 u = herein(iop->io_name, iop->io_flag&IOXHERE);
00401                 cp = "here file ";
00402                 break;
00403 
00404         case IOWRITE|IOCAT:
00405                 if ((u = open(cp, 1)) >= 0) {
00406                         lseek(u, (long)0, 2);
00407                         break;
00408                 }
00409         case IOWRITE:
00410                 u = creat(cp, 0666);
00411                 break;
00412 
00413         case IODUP:
00414                 u = dup2(*cp-'0', iop->io_unit);
00415                 break;
00416 
00417         case IOCLOSE:
00418                 close(iop->io_unit);
00419                 return(0);
00420         }
00421         if (u < 0) {
00422                 int e=errno;
00423                 prs(cp);
00424                 if (iop->io_flag&IOHERE) prs(iop->io_name);
00425                 prs(": cannot ");
00426                 prs(msg);
00427                 prs(" (");
00428                 prs(strerror(e));
00429                 warn(")");
00430                 return(1);
00431         } else {
00432                 if (u != iop->io_unit) {
00433                         dup2(u, iop->io_unit);
00434                         close(u);
00435                 }
00436         }
00437         return(0);
00438 }
00439 
00440 static void
00441 echo(wp)
00442 register char **wp;
00443 {
00444         register i;
00445 
00446         prs("+");
00447         for (i=0; wp[i]; i++) {
00448                 if (i)
00449                         prs(" ");
00450                 prs(wp[i]);
00451         }
00452         prs("\n");
00453 }
00454 
00455 static struct op **
00456 find1case(t, w)
00457 struct op *t;
00458 char *w;
00459 {
00460         register struct op *t1;
00461         struct op **tp;
00462         register char **wp, *cp;
00463 
00464         if (t == NULL)
00465                 return((struct op **)NULL);
00466         if (t->type == TLIST) {
00467                 if ((tp = find1case(t->left, w)) != NULL)
00468                         return(tp);
00469                 t1 = t->right;  /* TPAT */
00470         } else
00471                 t1 = t;
00472         for (wp = t1->words; *wp;)
00473                 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
00474                         return(&t1->left);
00475         return((struct op **)NULL);
00476 }
00477 
00478 static struct op *
00479 findcase(t, w)
00480 struct op *t;
00481 char *w;
00482 {
00483         register struct op **tp;
00484 
00485         return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
00486 }
00487 
00488 /*
00489  * Enter a new loop level (marked for break/continue).
00490  */
00491 static void
00492 brkset(bc)
00493 struct brkcon *bc;
00494 {
00495         bc->nextlev = brklist;
00496         brklist = bc;
00497 }
00498 
00499 /*
00500  * Wait for the last process created.
00501  * Print a message for each process found
00502  * that was killed by a signal.
00503  * Ignore interrupt signals while waiting
00504  * unless `canintr' is true.
00505  */
00506 int
00507 waitfor(lastpid, canintr)
00508 register int lastpid;
00509 int canintr;
00510 {
00511         register int pid, rv;
00512         int s;
00513         int oheedint = heedint;
00514 
00515         heedint = 0;
00516         rv = 0;
00517         do {
00518                 pid = wait(&s);
00519                 if (pid == -1) {
00520                         if (errno != EINTR || canintr)
00521                                 break;
00522                 } else {
00523                         if ((rv = WAITSIG(s)) != 0) {
00524                                 if (rv < NSIGNAL) {
00525                                         if (signame[rv] != NULL) {
00526                                                 if (pid != lastpid) {
00527                                                         prn(pid);
00528                                                         prs(": ");
00529                                                 }
00530                                                 prs(signame[rv]);
00531                                         }
00532                                 } else {
00533                                         if (pid != lastpid) {
00534                                                 prn(pid);
00535                                                 prs(": ");
00536                                         }
00537                                         prs("Signal "); prn(rv); prs(" ");
00538                                 }
00539                                 if (WAITCORE(s))
00540                                         prs(" - core dumped");
00541                                 if (rv >= NSIGNAL || signame[rv])
00542                                         prs("\n");
00543                                 rv = -1;
00544                         } else
00545                                 rv = WAITVAL(s);
00546                 }
00547         } while (pid != lastpid);
00548         heedint = oheedint;
00549         if (intr)
00550                 if (talking) {
00551                         if (canintr)
00552                                 intr = 0;
00553                 } else {
00554                         if (exstat == 0) exstat = rv;
00555                         onintr(0);
00556                 }
00557         return(rv);
00558 }
00559 
00560 int
00561 setstatus(s)
00562 register int s;
00563 {
00564         exstat = s;
00565         setval(lookup("?"), putn(s));
00566         return(s);
00567 }
00568 
00569 /*
00570  * PATH-searching interface to execve.
00571  * If getenv("PATH") were kept up-to-date,
00572  * execvp might be used.
00573  */
00574 char *
00575 rexecve(c, v, envp)
00576 char *c, **v, **envp;
00577 {
00578         register int i;
00579         register char *sp, *tp;
00580         int eacces = 0, asis = 0;
00581 
00582         sp = any('/', c)? "": path->value;
00583         asis = *sp == '\0';
00584         while (asis || *sp != '\0') {
00585                 asis = 0;
00586                 tp = e.linep;
00587                 for (; *sp != '\0'; tp++)
00588                         if ((*tp = *sp++) == ':') {
00589                                 asis = *sp == '\0';
00590                                 break;
00591                         }
00592                 if (tp != e.linep)
00593                         *tp++ = '/';
00594                 for (i = 0; (*tp++ = c[i++]) != '\0';)
00595                         ;
00596                 execve(e.linep, v, envp);
00597                 switch (errno) {
00598                 case ENOEXEC:
00599                         *v = e.linep;
00600                         tp = *--v;
00601                         *v = e.linep;
00602                         execve("/bin/sh", v, envp);
00603                         *v = tp;
00604                         return("no Shell");
00605 
00606                 case ENOMEM:
00607                         return("program too big");
00608 
00609                 case E2BIG:
00610                         return("argument list too long");
00611 
00612                 case EACCES:
00613                         eacces++;
00614                         break;
00615                 }
00616         }
00617         return(errno==ENOENT ? "not found" : "cannot execute");
00618 }
00619 
00620 /*
00621  * Run the command produced by generator `f'
00622  * applied to stream `arg'.
00623  */
00624 int
00625 run(argp, f)
00626 struct ioarg *argp;
00627 int (*f)();
00628 {
00629         struct op *otree;
00630         struct wdblock *swdlist;
00631         struct wdblock *siolist;
00632         jmp_buf ev, rt;
00633         xint *ofail;
00634         int rv;
00635 
00636         areanum++;
00637         swdlist = wdlist;
00638         siolist = iolist;
00639         otree = outtree;
00640         ofail = failpt;
00641         rv = -1;
00642         if (newenv(setjmp(errpt = ev)) == 0) {
00643                 wdlist = 0;
00644                 iolist = 0;
00645                 pushio(argp, f);
00646                 e.iobase = e.iop;
00647                 yynerrs = 0;
00648                 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
00649                         rv = execute(outtree, NOPIPE, NOPIPE, 0);
00650                 quitenv();
00651         }
00652         wdlist = swdlist;
00653         iolist = siolist;
00654         failpt = ofail;
00655         outtree = otree;
00656         freearea(areanum--);
00657         return(rv);
00658 }
00659 
00660 /* -------- do.c -------- */
00661 /* #include "sh.h" */
00662 
00663 /*
00664  * built-in commands: doX
00665  */
00666 
00667 int
00668 dolabel()
00669 {
00670         return(0);
00671 }
00672 
00673 int
00674 dochdir(t)
00675 register struct op *t;
00676 {
00677         register char *cp, *er;
00678 
00679         if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
00680                 er = ": no home directory";
00681         else if(chdir(cp) < 0)
00682                 er = ": bad directory";
00683         else
00684                 return(0);
00685         prs(cp != NULL? cp: "cd");
00686         err(er);
00687         return(1);
00688 }
00689 
00690 int
00691 doshift(t)
00692 register struct op *t;
00693 {
00694         register n;
00695 
00696         n = t->words[1]? getn(t->words[1]): 1;
00697         if(dolc < n) {
00698                 err("nothing to shift");
00699                 return(1);
00700         }
00701         dolv[n] = dolv[0];
00702         dolv += n;
00703         dolc -= n;
00704         setval(lookup("#"), putn(dolc));
00705         return(0);
00706 }
00707 
00708 /*
00709  * execute login and newgrp directly
00710  */
00711 int
00712 dologin(t)
00713 struct op *t;
00714 {
00715         register char *cp;
00716 
00717         if (talking) {
00718                 signal(SIGINT, SIG_DFL);
00719                 signal(SIGQUIT, SIG_DFL);
00720         }
00721         cp = rexecve(t->words[0], t->words, makenv());
00722         prs(t->words[0]); prs(": "); err(cp);
00723         return(1);
00724 }
00725 
00726 int
00727 doumask(t)
00728 register struct op *t;
00729 {
00730         register int i, n;
00731         register char *cp;
00732 
00733         if ((cp = t->words[1]) == NULL) {
00734                 i = umask(0);
00735                 umask(i);
00736                 for (n=3*4; (n-=3) >= 0;)
00737                         putc('0'+((i>>n)&07));
00738                 putc('\n');
00739         } else {
00740                 for (n=0; *cp>='0' && *cp<='9'; cp++)
00741                         n = n*8 + (*cp-'0');
00742                 umask(n);
00743         }
00744         return(0);
00745 }
00746 
00747 int
00748 doexec(t)
00749 register struct op *t;
00750 {
00751         register i;
00752         jmp_buf ex;
00753         xint *ofail;
00754 
00755         t->ioact = NULL;
00756         for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
00757                 ;
00758         if (i == 0)
00759                 return(1);
00760         execflg = 1;
00761         ofail = failpt;
00762         if (setjmp(failpt = ex) == 0)
00763                 execute(t, NOPIPE, NOPIPE, FEXEC);
00764         failpt = ofail;
00765         execflg = 0;
00766         return(1);
00767 }
00768 
00769 int
00770 dodot(t)
00771 struct op *t;
00772 {
00773         register i;
00774         register char *sp, *tp;
00775         char *cp;
00776 
00777         if ((cp = t->words[1]) == NULL)
00778                 return(0);
00779         sp = any('/', cp)? ":": path->value;
00780         while (*sp) {
00781                 tp = e.linep;
00782                 while (*sp && (*tp = *sp++) != ':')
00783                         tp++;
00784                 if (tp != e.linep)
00785                         *tp++ = '/';
00786                 for (i = 0; (*tp++ = cp[i++]) != '\0';)
00787                         ;
00788                 if ((i = open(e.linep, 0)) >= 0) {
00789                         exstat = 0;
00790                         next(remap(i));
00791                         return(exstat);
00792                 }
00793         }
00794         prs(cp);
00795         err(": not found");
00796         return(-1);
00797 }
00798 
00799 int
00800 dowait(t)
00801 struct op *t;
00802 {
00803         register i;
00804         register char *cp;
00805 
00806         if ((cp = t->words[1]) != NULL) {
00807                 i = getn(cp);
00808                 if (i == 0)
00809                         return(0);
00810         } else
00811                 i = -1;
00812         setstatus(waitfor(i, 1));
00813         return(0);
00814 }
00815 
00816 int
00817 doread(t)
00818 struct op *t;
00819 {
00820         register char *cp, **wp;
00821         register nb;
00822         register int  nl = 0;
00823 
00824         if (t->words[1] == NULL) {
00825                 err("Usage: read name ...");
00826                 return(1);
00827         }
00828         for (wp = t->words+1; *wp; wp++) {
00829                 for (cp = e.linep; !nl && cp < elinep-1; cp++)
00830                         if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
00831                             (nl = (*cp == '\n')) ||
00832                             (wp[1] && any(*cp, ifs->value)))
00833                                 break;
00834                 *cp = 0;
00835                 if (nb <= 0)
00836                         break;
00837                 setval(lookup(*wp), e.linep);
00838         }
00839         return(nb <= 0);
00840 }
00841 
00842 int
00843 doeval(t)
00844 register struct op *t;
00845 {
00846         return(RUN(awordlist, t->words+1, wdchar));
00847 }
00848 
00849 int
00850 dotrap(t)
00851 register struct op *t;
00852 {
00853         register int  n, i;
00854         register int  resetsig;
00855 
00856         if (t->words[1] == NULL) {
00857                 for (i=0; i<=_NSIG; i++)
00858                         if (trap[i]) {
00859                                 prn(i);
00860                                 prs(": ");
00861                                 prs(trap[i]);
00862                                 prs("\n");
00863                         }
00864                 return(0);
00865         }
00866         resetsig = digit(*t->words[1]);
00867         for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
00868                 n = getsig(t->words[i]);
00869                 xfree(trap[n]);
00870                 trap[n] = 0;
00871                 if (!resetsig) {
00872                         if (*t->words[1] != '\0') {
00873                                 trap[n] = strsave(t->words[1], 0);
00874                                 setsig(n, sig);
00875                         } else
00876                                 setsig(n, SIG_IGN);
00877                 } else {
00878                         if (talking)
00879                                 if (n == SIGINT)
00880                                         setsig(n, onintr);
00881                                 else
00882                                         setsig(n, n == SIGQUIT ? SIG_IGN 
00883                                                                : SIG_DFL);
00884                         else
00885                                 setsig(n, SIG_DFL);
00886                 }
00887         }
00888         return(0);
00889 }
00890 
00891 int
00892 getsig(s)
00893 char *s;
00894 {
00895         register int n;
00896 
00897         if ((n = getn(s)) < 0 || n > _NSIG) {
00898                 err("trap: bad signal number");
00899                 n = 0;
00900         }
00901         return(n);
00902 }
00903 
00904 void
00905 setsig(n, f)
00906 register n;
00907 _PROTOTYPE(void (*f), (int));
00908 {
00909         if (n == 0)
00910                 return;
00911         if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
00912                 ourtrap[n] = 1;
00913                 signal(n, f);
00914         }
00915 }
00916 
00917 int
00918 getn(as)
00919 char *as;
00920 {
00921         register char *s;
00922         register n, m;
00923 
00924         s = as;
00925         m = 1;
00926         if (*s == '-') {
00927                 m = -1;
00928                 s++;
00929         }
00930         for (n = 0; digit(*s); s++)
00931                 n = (n*10) + (*s-'0');
00932         if (*s) {
00933                 prs(as);
00934                 err(": bad number");
00935         }
00936         return(n*m);
00937 }
00938 
00939 int
00940 dobreak(t)
00941 struct op *t;
00942 {
00943         return(brkcontin(t->words[1], 1));
00944 }
00945 
00946 int
00947 docontinue(t)
00948 struct op *t;
00949 {
00950         return(brkcontin(t->words[1], 0));
00951 }
00952 
00953 static int
00954 brkcontin(cp, val)
00955 register char *cp;
00956 int val;
00957 {
00958         register struct brkcon *bc;
00959         register nl;
00960 
00961         nl = cp == NULL? 1: getn(cp);
00962         if (nl <= 0)
00963                 nl = 999;
00964         do {
00965                 if ((bc = brklist) == NULL)
00966                         break;
00967                 brklist = bc->nextlev;
00968         } while (--nl);
00969         if (nl) {
00970                 err("bad break/continue level");
00971                 return(1);
00972         }
00973         isbreak = val;
00974         longjmp(bc->brkpt, 1);
00975         /* NOTREACHED */
00976 }
00977 
00978 int
00979 doexit(t)
00980 struct op *t;
00981 {
00982         register char *cp;
00983 
00984         execflg = 0;
00985         if ((cp = t->words[1]) != NULL)
00986                 setstatus(getn(cp));
00987         leave();
00988         /* NOTREACHED */
00989 }
00990 
00991 int
00992 doexport(t)
00993 struct op *t;
00994 {
00995         rdexp(t->words+1, export, EXPORT);
00996         return(0);
00997 }
00998 
00999 int
01000 doreadonly(t)
01001 struct op *t;
01002 {
01003         rdexp(t->words+1, ronly, RONLY);
01004         return(0);
01005 }
01006 
01007 static void
01008 rdexp(wp, f, key)
01009 register char **wp;
01010 void (*f)();
01011 int key;
01012 {
01013         if (*wp != NULL) {
01014                 for (; *wp != NULL; wp++)
01015                         if (checkname(*wp))
01016                                 (*f)(lookup(*wp));
01017                         else
01018                                 badid(*wp);
01019         } else
01020                 putvlist(key, 1);
01021 }
01022 
01023 static void
01024 badid(s)
01025 register char *s;
01026 {
01027         prs(s);
01028         err(": bad identifier");
01029 }
01030 
01031 int
01032 doset(t)
01033 register struct op *t;
01034 {
01035         register struct var *vp;
01036         register char *cp;
01037         register n;
01038 
01039         if ((cp = t->words[1]) == NULL) {
01040                 for (vp = vlist; vp; vp = vp->next)
01041                         varput(vp->name, 1);
01042                 return(0);
01043         }
01044         if (*cp == '-') {
01045                 /* bad: t->words++; */
01046                 for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
01047                         ;
01048                 if (*++cp == 0)
01049                         flag['x'] = flag['v'] = 0;
01050                 else
01051                         for (; *cp; cp++)
01052                                 switch (*cp) {
01053                                 case 'e':
01054                                         if (!talking)
01055                                                 flag['e']++;
01056                                         break;
01057 
01058                                 default:
01059                                         if (*cp>='a' && *cp<='z')
01060                                                 flag[*cp]++;
01061                                         break;
01062                                 }
01063                 setdash();
01064         }
01065         if (t->words[1]) {
01066                 t->words[0] = dolv[0];
01067                 for (n=1; t->words[n]; n++)
01068                         setarea((char *)t->words[n], 0);
01069                 dolc = n-1;
01070                 dolv = t->words;
01071                 setval(lookup("#"), putn(dolc));
01072                 setarea((char *)(dolv-1), 0);
01073         }
01074         return(0);
01075 }
01076 
01077 void
01078 varput(s, out)
01079 register char *s;
01080 int out;
01081 {
01082         if (letnum(*s)) {
01083                 write(out, s, strlen(s));
01084                 write(out, "\n", 1);
01085         }
01086 }
01087 
01088 
01089 #define SECS    60L
01090 #define MINS    3600L
01091 
01092 int
01093 dotimes()
01094 {
01095         struct tms tbuf;
01096 
01097         times(&tbuf);
01098 
01099         prn((int)(tbuf.tms_cutime / MINS));
01100         prs("m");
01101         prn((int)((tbuf.tms_cutime % MINS) / SECS));
01102         prs("s ");
01103         prn((int)(tbuf.tms_cstime / MINS));
01104         prs("m");
01105         prn((int)((tbuf.tms_cstime % MINS) / SECS));
01106         prs("s\n");
01107         return(0);
01108 }
01109 
01110 struct  builtin {
01111         char    *command;
01112         int     (*fn)();
01113 };
01114 static struct   builtin builtin[] = {
01115         ":",            dolabel,
01116         "cd",           dochdir,
01117         "shift",        doshift,
01118         "exec",         doexec,
01119         "wait",         dowait,
01120         "read",         doread,
01121         "eval",         doeval,
01122         "trap",         dotrap,
01123         "break",        dobreak,
01124         "continue",     docontinue,
01125         "exit",         doexit,
01126         "export",       doexport,
01127         "readonly",     doreadonly,
01128         "set",          doset,
01129         ".",            dodot,
01130         "umask",        doumask,
01131         "login",        dologin,
01132         "newgrp",       dologin,
01133         "times",        dotimes,
01134         0,
01135 };
01136 
01137 int (*inbuilt(s))()
01138 register char *s;
01139 {
01140         register struct builtin *bp;
01141 
01142         for (bp = builtin; bp->command != NULL; bp++)
01143                 if (strcmp(bp->command, s) == 0)
01144                         return(bp->fn);
01145         return((int(*)())NULL);
01146 }
01147 

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