sh5.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 "sh.h"
00007 
00008 /* -------- io.c -------- */
00009 /* #include "sh.h" */
00010 
00011 /*
00012  * shell IO
00013  */
00014 
00015 static struct iobuf sharedbuf = {AFID_NOBUF};
00016 static struct iobuf mainbuf = {AFID_NOBUF};
00017 static unsigned bufid = AFID_ID;        /* buffer id counter */
00018 
00019 struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0};
00020 
00021 _PROTOTYPE(static void readhere, (char **name, char *s, int ec ));
00022 _PROTOTYPE(void pushio, (struct ioarg *argp, int (*fn)()));
00023 _PROTOTYPE(static int xxchar, (struct ioarg *ap ));
00024 _PROTOTYPE(void tempname, (char *tname ));
00025 
00026 int
00027 getc(ec)
00028 register int ec;
00029 {
00030         register int c;
00031 
00032         if(e.linep > elinep) {
00033                 while((c=readc()) != '\n' && c)
00034                         ;
00035                 err("input line too long");
00036                 gflg++;
00037                 return(c);
00038         }
00039         c = readc();
00040         if (ec != '\'' && e.iop->task != XGRAVE) {
00041                 if(c == '\\') {
00042                         c = readc();
00043                         if (c == '\n' && ec != '\"')
00044                                 return(getc(ec));
00045                         c |= QUOTE;
00046                 }
00047         }
00048         return(c);
00049 }
00050 
00051 void
00052 unget(c)
00053 int c;
00054 {
00055         if (e.iop >= e.iobase)
00056                 e.iop->peekc = c;
00057 }
00058 
00059 int
00060 eofc()
00061 
00062 {
00063   return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
00064 }
00065 
00066 int
00067 readc()
00068 {
00069         register c;
00070 
00071         for (; e.iop >= e.iobase; e.iop--)
00072                 if ((c = e.iop->peekc) != '\0') {
00073                         e.iop->peekc = 0;
00074                         return(c);
00075                 }
00076                 else {
00077                     if (e.iop->prev != 0) {
00078                         if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') {
00079                                 if (c == -1) {
00080                                         e.iop++;
00081                                         continue;
00082                                 }
00083                                 if (e.iop == iostack)
00084                                         ioecho(c);
00085                                 return(e.iop->prev = c);
00086                         }
00087                         else if (e.iop->task == XIO && e.iop->prev != '\n') {
00088                                 e.iop->prev = 0;
00089                                 if (e.iop == iostack)
00090                                         ioecho('\n');
00091                                 return '\n';
00092                         }
00093                     }
00094                     if (e.iop->task == XIO) {
00095                         if (multiline)
00096                             return e.iop->prev = 0;
00097                         if (talking && e.iop == iostack+1)
00098                             prs(prompt->value);
00099                     }
00100                 }
00101         if (e.iop >= iostack)
00102                 return(0);
00103         leave();
00104         /* NOTREACHED */
00105 }
00106 
00107 void
00108 ioecho(c)
00109 char c;
00110 {
00111         if (flag['v'])
00112                 write(2, &c, sizeof c);
00113 }
00114 
00115 void
00116 pushio(argp, fn)
00117 struct ioarg *argp;
00118 int (*fn)();
00119 {
00120         if (++e.iop >= &iostack[NPUSH]) {
00121                 e.iop--;
00122                 err("Shell input nested too deeply");
00123                 gflg++;
00124                 return;
00125         }
00126         e.iop->iofn = fn;
00127 
00128         if (argp->afid != AFID_NOBUF)
00129           e.iop->argp = argp;
00130         else {
00131           e.iop->argp  = ioargstack + (e.iop - iostack);
00132           *e.iop->argp = *argp;
00133           e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
00134           if (isatty(e.iop->argp->afile) == 0 &&
00135               (e.iop == &iostack[0] ||
00136                lseek(e.iop->argp->afile, 0L, 1) != -1)) {
00137             if (++bufid == AFID_NOBUF)
00138               bufid = AFID_ID;
00139             e.iop->argp->afid  = bufid;
00140           }
00141         }
00142 
00143         e.iop->prev  = ~'\n';
00144         e.iop->peekc = 0;
00145         e.iop->xchar = 0;
00146         e.iop->nlcount = 0;
00147         if (fn == filechar || fn == linechar)
00148                 e.iop->task = XIO;
00149         else if (fn == gravechar || fn == qgravechar)
00150                 e.iop->task = XGRAVE;
00151         else
00152                 e.iop->task = XOTHER;
00153 }
00154 
00155 struct io *
00156 setbase(ip)
00157 struct io *ip;
00158 {
00159         register struct io *xp;
00160 
00161         xp = e.iobase;
00162         e.iobase = ip;
00163         return(xp);
00164 }
00165 
00166 /*
00167  * Input generating functions
00168  */
00169 
00170 /*
00171  * Produce the characters of a string, then a newline, then EOF.
00172  */
00173 int
00174 nlchar(ap)
00175 register struct ioarg *ap;
00176 {
00177         register int c;
00178 
00179         if (ap->aword == NULL)
00180                 return(0);
00181         if ((c = *ap->aword++) == 0) {
00182                 ap->aword = NULL;
00183                 return('\n');
00184         }
00185         return(c);
00186 }
00187 
00188 /*
00189  * Given a list of words, produce the characters
00190  * in them, with a space after each word.
00191  */
00192 int
00193 wdchar(ap)
00194 register struct ioarg *ap;
00195 {
00196         register char c;
00197         register char **wl;
00198 
00199         if ((wl = ap->awordlist) == NULL)
00200                 return(0);
00201         if (*wl != NULL) {
00202                 if ((c = *(*wl)++) != 0)
00203                         return(c & 0177);
00204                 ap->awordlist++;
00205                 return(' ');
00206         }
00207         ap->awordlist = NULL;
00208         return('\n');
00209 }
00210 
00211 /*
00212  * Return the characters of a list of words,
00213  * producing a space between them.
00214  */
00215 int
00216 dolchar(ap)
00217 register struct ioarg *ap;
00218 {
00219         register char *wp;
00220 
00221         if ((wp = *ap->awordlist++) != NULL) {
00222                 PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar);
00223                 return(-1);
00224         }
00225         return(0);
00226 }
00227 
00228 static int
00229 xxchar(ap)
00230 register struct ioarg *ap;
00231 {
00232         register int c;
00233 
00234         if (ap->aword == NULL)
00235                 return(0);
00236         if ((c = *ap->aword++) == '\0') {
00237                 ap->aword = NULL;
00238                 return(' ');
00239         }
00240         return(c);
00241 }
00242 
00243 /*
00244  * Produce the characters from a single word (string).
00245  */
00246 int
00247 strchar(ap)
00248 register struct ioarg *ap;
00249 {
00250         register int c;
00251 
00252         if (ap->aword == NULL || (c = *ap->aword++) == 0)
00253                 return(0);
00254         return(c);
00255 }
00256 
00257 /*
00258  * Produce quoted characters from a single word (string).
00259  */
00260 int
00261 qstrchar(ap)
00262 register struct ioarg *ap;
00263 {
00264         register int c;
00265 
00266         if (ap->aword == NULL || (c = *ap->aword++) == 0)
00267                 return(0);
00268         return(c|QUOTE);
00269 }
00270 
00271 /*
00272  * Return the characters from a file.
00273  */
00274 int
00275 filechar(ap)
00276 register struct ioarg *ap;
00277 {
00278         register int i;
00279         char c;
00280         struct iobuf *bp = ap->afbuf;
00281 
00282         if (ap->afid != AFID_NOBUF) {
00283           if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
00284             if (i)
00285               lseek(ap->afile, ap->afpos, 0);
00286             do {
00287               i = read(ap->afile, bp->buf, sizeof(bp->buf));
00288             } while (i < 0 && errno == EINTR);
00289             if (i <= 0) {
00290               closef(ap->afile);
00291               return 0;
00292             }
00293             bp->id = ap->afid;
00294             bp->ebufp = (bp->bufp  = bp->buf) + i;
00295           }
00296           ap->afpos++;
00297           return *bp->bufp++ & 0177;
00298         }
00299 
00300         do {
00301                 i = read(ap->afile, &c, sizeof(c));
00302         } while (i < 0 && errno == EINTR);
00303         return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
00304 }
00305 
00306 /*
00307  * Return the characters from a here temp file.
00308  */
00309 int
00310 herechar(ap)
00311 register struct ioarg *ap;
00312 {
00313         char c;
00314 
00315 
00316         if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
00317                 close(ap->afile);
00318                 c = 0;
00319         }
00320         return (c);
00321 
00322 }
00323 
00324 /*
00325  * Return the characters produced by a process (`...`).
00326  * Quote them if required, and remove any trailing newline characters.
00327  */
00328 int
00329 gravechar(ap, iop)
00330 struct ioarg *ap;
00331 struct io *iop;
00332 {
00333         register int c;
00334 
00335         if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
00336                 c = ' ';
00337         return(c);
00338 }
00339 
00340 int
00341 qgravechar(ap, iop)
00342 register struct ioarg *ap;
00343 struct io *iop;
00344 {
00345         register int c;
00346 
00347         if (iop->xchar) {
00348                 if (iop->nlcount) {
00349                         iop->nlcount--;
00350                         return('\n'|QUOTE);
00351                 }
00352                 c = iop->xchar;
00353                 iop->xchar = 0;
00354         } else if ((c = filechar(ap)) == '\n') {
00355                 iop->nlcount = 1;
00356                 while ((c = filechar(ap)) == '\n')
00357                         iop->nlcount++;
00358                 iop->xchar = c;
00359                 if (c == 0)
00360                         return(c);
00361                 iop->nlcount--;
00362                 c = '\n';
00363         }
00364         return(c!=0? c|QUOTE: 0);
00365 }
00366 
00367 /*
00368  * Return a single command (usually the first line) from a file.
00369  */
00370 int
00371 linechar(ap)
00372 register struct ioarg *ap;
00373 {
00374         register int c;
00375 
00376         if ((c = filechar(ap)) == '\n') {
00377                 if (!multiline) {
00378                         closef(ap->afile);
00379                         ap->afile = -1; /* illegal value */
00380                 }
00381         }
00382         return(c);
00383 }
00384 
00385 void
00386 prs(s)
00387 register char *s;
00388 {
00389         if (*s)
00390                 write(2, s, strlen(s));
00391 }
00392 
00393 void
00394 putc(c)
00395 char c;
00396 {
00397         write(2, &c, sizeof c);
00398 }
00399 
00400 void
00401 prn(u)
00402 unsigned u;
00403 {
00404         prs(itoa(u, 0));
00405 }
00406 
00407 void
00408 closef(i)
00409 register int i;
00410 {
00411         if (i > 2)
00412                 close(i);
00413 }
00414 
00415 void
00416 closeall()
00417 {
00418         register u;
00419 
00420         for (u=NUFILE; u<NOFILE;)
00421                 close(u++);
00422 }
00423 
00424 /*
00425  * remap fd into Shell's fd space
00426  */
00427 int
00428 remap(fd)
00429 register int fd;
00430 {
00431         register int i;
00432         int map[NOFILE];
00433 
00434         if (fd < e.iofd) {
00435                 for (i=0; i<NOFILE; i++)
00436                         map[i] = 0;
00437                 do {
00438                         map[fd] = 1;
00439                         fd = dup(fd);
00440                 } while (fd >= 0 && fd < e.iofd);
00441                 for (i=0; i<NOFILE; i++)
00442                         if (map[i])
00443                                 close(i);
00444                 if (fd < 0)
00445                         err("too many files open in shell");
00446         }
00447         return(fd);
00448 }
00449 
00450 int
00451 openpipe(pv)
00452 register int *pv;
00453 {
00454         register int i;
00455 
00456         if ((i = pipe(pv)) < 0)
00457                 err("can't create pipe - try again");
00458         return(i);
00459 }
00460 
00461 void
00462 closepipe(pv)
00463 register int *pv;
00464 {
00465         if (pv != NULL) {
00466                 close(*pv++);
00467                 close(*pv);
00468         }
00469 }
00470 
00471 /* -------- here.c -------- */
00472 /* #include "sh.h" */
00473 
00474 /*
00475  * here documents
00476  */
00477 
00478 struct  here {
00479         char    *h_tag;
00480         int     h_dosub;
00481         struct  ioword *h_iop;
00482         struct  here    *h_next;
00483 };
00484 
00485 static  struct here *inhere;            /* list of hear docs while parsing */
00486 static  struct here *acthere;           /* list of active here documents */
00487 
00488 void
00489 inithere()
00490 {
00491         inhere=acthere=(struct here*)0;
00492 }
00493 
00494 void
00495 markhere(s, iop)
00496 register char *s;
00497 struct ioword *iop;
00498 {
00499         register struct here *h, *lh;
00500 
00501         h = (struct here *) space(sizeof(struct here));
00502         if (h == 0)
00503                 return;
00504         h->h_tag = evalstr(s, DOSUB);
00505         if (h->h_tag == 0)
00506                 return;
00507         h->h_iop = iop;
00508         iop->io_name = 0;
00509         h->h_next = NULL;
00510         if (inhere == 0)
00511                 inhere = h;
00512         else
00513                 for (lh = inhere; lh!=NULL; lh = lh->h_next)
00514                         if (lh->h_next == 0) {
00515                                 lh->h_next = h;
00516                                 break;
00517                         }
00518         iop->io_flag |= IOHERE|IOXHERE;
00519         for (s = h->h_tag; *s; s++)
00520                 if (*s & QUOTE) {
00521                         iop->io_flag &= ~ IOXHERE;
00522                         *s &= ~ QUOTE;
00523                 }
00524         h->h_dosub = iop->io_flag & IOXHERE;
00525 }
00526 
00527 void
00528 gethere()
00529 {
00530         register struct here *h, *hp;
00531 
00532         /* Scan here files first leaving inhere list in place */
00533         for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
00534           readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\'');
00535 
00536         /* Make inhere list active - keep list intact for scraphere */
00537         if (hp != NULL) {
00538           hp->h_next = acthere;
00539           acthere    = inhere;
00540           inhere     = NULL;
00541         }
00542 }
00543 
00544 static void
00545 readhere(name, s, ec)
00546 char **name;
00547 register char *s;
00548 int ec;
00549 {
00550         int tf;
00551         char tname[30];
00552         register c;
00553         jmp_buf ev;
00554         char line [LINELIM+1];
00555         char *next;
00556 
00557         tempname(tname);
00558         *name = strsave(tname, areanum);
00559         tf = creat(tname, 0600);
00560         if (tf < 0)
00561                 return;
00562         if (newenv(setjmp(errpt = ev)) != 0)
00563                 unlink(tname);
00564         else {
00565                 pushio(e.iop->argp, e.iop->iofn);
00566                 e.iobase = e.iop;
00567                 for (;;) {
00568                         if (talking && e.iop <= iostack)
00569                                 prs(cprompt->value);
00570                         next = line;
00571                         while ((c = readc()) != '\n' && c) {
00572                                 if (next >= &line[LINELIM]) {
00573                                         c = 0;
00574                                         break;
00575                                 }
00576                                 *next++ = c;
00577                         }
00578                         *next = 0;
00579                         if (strcmp(s, line) == 0 || c == 0)
00580                                 break;
00581                         *next++ = '\n';
00582                         write (tf, line, (int)(next-line));
00583                 }
00584                 if (c == 0) {
00585                         prs("here document `"); prs(s); err("' unclosed");
00586                 }
00587                 quitenv();
00588         }
00589         close(tf);
00590 }
00591 
00592 /*
00593  * open here temp file.
00594  * if unquoted here, expand here temp file into second temp file.
00595  */
00596 int
00597 herein(hname, xdoll)
00598 char *hname;
00599 int xdoll;
00600 {
00601         register hf, tf;
00602 
00603         if (hname == 0)
00604                 return(-1);
00605         hf = open(hname, 0);
00606         if (hf < 0)
00607                 return (-1);
00608         if (xdoll) {
00609                 char c;
00610                 char tname[30];
00611                 jmp_buf ev;
00612 
00613                 tempname(tname);
00614                 if ((tf = creat(tname, 0600)) < 0)
00615                         return (-1);
00616                 if (newenv(setjmp(errpt = ev)) == 0) {
00617                         PUSHIO(afile, hf, herechar);
00618                         setbase(e.iop);
00619                         while ((c = subgetc(0, 0)) != 0) {
00620                                 char c1 = c&~QUOTE;
00621 
00622                                 if (c&QUOTE && !any(c1,"`$\\"))
00623                                         write(tf,"\\",1);
00624                                 write(tf, &c1, 1);
00625                         }
00626                         quitenv();
00627                 } else
00628                         unlink(tname);
00629                 close(tf);
00630                 tf = open(tname, 0);
00631                 unlink(tname);
00632                 return (tf);
00633         } else
00634                 return (hf);
00635 }
00636 
00637 void
00638 scraphere()
00639 {
00640         register struct here *h;
00641 
00642         for (h = inhere; h != NULL; h = h->h_next) {
00643                 if (h->h_iop && h->h_iop->io_name)
00644                   unlink(h->h_iop->io_name);
00645         }
00646         inhere = NULL;
00647 }
00648 
00649 /* unlink here temp files before a freearea(area) */
00650 void
00651 freehere(area)
00652 int area;
00653 {
00654         register struct here *h, *hl;
00655 
00656         hl = NULL;
00657         for (h = acthere; h != NULL; h = h->h_next)
00658                 if (getarea((char *) h) >= area) {
00659                         if (h->h_iop->io_name != NULL)
00660                                 unlink(h->h_iop->io_name);
00661                         if (hl == NULL)
00662                                 acthere = h->h_next;
00663                         else
00664                                 hl->h_next = h->h_next;
00665                 } else
00666                         hl = h;
00667 }
00668 
00669 void
00670 tempname(tname)
00671 char *tname;
00672 {
00673         static int inc;
00674         register char *cp, *lp;
00675 
00676         for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++)
00677                 ;
00678         lp = putn(getpid()*1000 + inc++);
00679         for (; (*cp = *lp++) != '\0'; cp++)
00680                 ;
00681 }

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