172339Sabial#define Extern extern 272339Sabial#include <sys/types.h> 372339Sabial#include <signal.h> 472339Sabial#define _NSIG NSIG 572339Sabial#include <errno.h> 672339Sabial#include <setjmp.h> 772339Sabial#include "sh.h" 872339Sabial/* -------- sh.c -------- */ 972339Sabial/* 1072339Sabial * shell 1172339Sabial */ 1272339Sabial 1372339Sabial/* #include "sh.h" */ 1472339Sabial 1572339Sabialint intr; 1672339Sabialint inparse; 1772339Sabialchar flags['z'-'a'+1]; 1872339Sabialchar *flag = flags-'a'; 1972339Sabialchar *elinep = line+sizeof(line)-5; 2072339Sabialchar *null = ""; 2172339Sabialint heedint =1; 2272339Sabialstruct env e ={line, iostack, iostack-1, 2372339Sabial (xint *)NULL, FDBASE, (struct env *)NULL}; 2472339Sabial 2572339Sabialextern char **environ; /* environment pointer */ 2672339Sabial 2772339Sabial/* 2872339Sabial * default shell, search rules 2972339Sabial */ 3072339Sabialchar shellname[] = "/bin/sh"; 3172339Sabialchar search[] = ":/bin:/usr/bin"; 3272339Sabial 3372339Sabial_PROTOTYPE(void (*qflag), (int)) = SIG_IGN; 3472339Sabial 3572339Sabial_PROTOTYPE(int main, (int argc, char **argv )); 3672339Sabial_PROTOTYPE(int newfile, (char *s )); 3772339Sabial_PROTOTYPE(static char *findeq, (char *cp )); 3872339Sabial_PROTOTYPE(static char *cclass, (char *p, int sub )); 3972339Sabial_PROTOTYPE(void initarea, (void)); 4072339Sabial 4172339Sabialint main(argc, argv) 4272339Sabialint argc; 4372339Sabialregister char **argv; 4472339Sabial{ 4572339Sabial register int f; 4672339Sabial register char *s; 4772339Sabial int cflag; 4872339Sabial char *name, **ap; 4972339Sabial int (*iof)(); 5072339Sabial 5172339Sabial initarea(); 5272339Sabial if ((ap = environ) != NULL) { 5372339Sabial while (*ap) 5472339Sabial assign(*ap++, !COPYV); 5572339Sabial for (ap = environ; *ap;) 5672339Sabial export(lookup(*ap++)); 5772339Sabial } 5872339Sabial closeall(); 5972339Sabial areanum = 1; 6072339Sabial 6172339Sabial shell = lookup("SHELL"); 6272339Sabial if (shell->value == null) 6372339Sabial setval(shell, shellname); 6472339Sabial export(shell); 6572339Sabial 6672339Sabial homedir = lookup("HOME"); 6772339Sabial if (homedir->value == null) 6872339Sabial setval(homedir, "/"); 6972339Sabial export(homedir); 7072339Sabial 7172339Sabial setval(lookup("$"), itoa(getpid(), 5)); 7272339Sabial 7372339Sabial path = lookup("PATH"); 7472339Sabial if (path->value == null) 7572339Sabial setval(path, search); 7672339Sabial export(path); 7772339Sabial 7872339Sabial ifs = lookup("IFS"); 7972339Sabial if (ifs->value == null) 8072339Sabial setval(ifs, " \t\n"); 8172339Sabial 8272339Sabial prompt = lookup("PS1"); 8372339Sabial if (prompt->value == null) 8472339Sabial#ifndef UNIXSHELL 8572339Sabial setval(prompt, "$ "); 8672339Sabial#else 8772339Sabial setval(prompt, "% "); 8872339Sabial#endif 8972339Sabial 9072339Sabial if (geteuid() == 0) { 9172339Sabial setval(prompt, "# "); 9272339Sabial prompt->status &= ~EXPORT; 9372339Sabial } 9472339Sabial cprompt = lookup("PS2"); 9572339Sabial if (cprompt->value == null) 9672339Sabial setval(cprompt, "> "); 9772339Sabial 9872339Sabial iof = filechar; 9972339Sabial cflag = 0; 10072339Sabial name = *argv++; 10172339Sabial if (--argc >= 1) { 10272339Sabial if(argv[0][0] == '-' && argv[0][1] != '\0') { 10372339Sabial for (s = argv[0]+1; *s; s++) 10472339Sabial switch (*s) { 10572339Sabial case 'c': 10672339Sabial prompt->status &= ~EXPORT; 10772339Sabial cprompt->status &= ~EXPORT; 10872339Sabial setval(prompt, ""); 10972339Sabial setval(cprompt, ""); 11072339Sabial cflag = 1; 11172339Sabial if (--argc > 0) 11272339Sabial PUSHIO(aword, *++argv, iof = nlchar); 11372339Sabial break; 11472339Sabial 11572339Sabial case 'q': 11672339Sabial qflag = SIG_DFL; 11772339Sabial break; 11872339Sabial 11972339Sabial case 's': 12072339Sabial /* standard input */ 12172339Sabial break; 12272339Sabial 12372339Sabial case 't': 12472339Sabial prompt->status &= ~EXPORT; 12572339Sabial setval(prompt, ""); 12672339Sabial iof = linechar; 12772339Sabial break; 12872339Sabial 12972339Sabial case 'i': 13072339Sabial talking++; 13172339Sabial default: 13272339Sabial if (*s>='a' && *s<='z') 13372339Sabial flag[*s]++; 13472339Sabial } 13572339Sabial } else { 13672339Sabial argv--; 13772339Sabial argc++; 13872339Sabial } 13972339Sabial if (iof == filechar && --argc > 0) { 14072339Sabial setval(prompt, ""); 14172339Sabial setval(cprompt, ""); 14272339Sabial prompt->status &= ~EXPORT; 14372339Sabial cprompt->status &= ~EXPORT; 14472339Sabial if (newfile(name = *++argv)) 14572339Sabial exit(1); 14672339Sabial } 14772339Sabial } 14872339Sabial setdash(); 14972339Sabial if (e.iop < iostack) { 15072339Sabial PUSHIO(afile, 0, iof); 15172339Sabial if (isatty(0) && isatty(1) && !cflag) 15272339Sabial talking++; 15372339Sabial } 15472339Sabial signal(SIGQUIT, qflag); 15572339Sabial if (name && name[0] == '-') { 15672339Sabial talking++; 15772339Sabial if ((f = open(".profile", 0)) >= 0) 15872339Sabial next(remap(f)); 15972339Sabial if ((f = open("/etc/profile", 0)) >= 0) 16072339Sabial next(remap(f)); 16172339Sabial } 16272339Sabial if (talking) 16372339Sabial signal(SIGTERM, sig); 16472339Sabial if (signal(SIGINT, SIG_IGN) != SIG_IGN) 16572339Sabial signal(SIGINT, onintr); 16672339Sabial dolv = argv; 16772339Sabial dolc = argc; 16872339Sabial dolv[0] = name; 16972339Sabial if (dolc > 1) 17072339Sabial for (ap = ++argv; --argc > 0;) 17172339Sabial if (assign(*ap = *argv++, !COPYV)) 17272339Sabial dolc--; /* keyword */ 17372339Sabial else 17472339Sabial ap++; 17572339Sabial setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); 17672339Sabial 17772339Sabial for (;;) { 17872339Sabial if (talking && e.iop <= iostack) 17972339Sabial prs(prompt->value); 18072339Sabial onecommand(); 18172339Sabial } 18272339Sabial} 18372339Sabial 18472339Sabialvoid 18572339Sabialsetdash() 18672339Sabial{ 18772339Sabial register char *cp, c; 18872339Sabial char m['z'-'a'+1]; 18972339Sabial 19072339Sabial cp = m; 19172339Sabial for (c='a'; c<='z'; c++) 19272339Sabial if (flag[c]) 19372339Sabial *cp++ = c; 19472339Sabial *cp = 0; 19572339Sabial setval(lookup("-"), m); 19672339Sabial} 19772339Sabial 19872339Sabialint 19972339Sabialnewfile(s) 20072339Sabialregister char *s; 20172339Sabial{ 20272339Sabial register f; 20372339Sabial 20472339Sabial if (strcmp(s, "-") != 0) { 20572339Sabial f = open(s, 0); 20672339Sabial if (f < 0) { 20772339Sabial prs(s); 20872339Sabial err(": cannot open"); 20972339Sabial return(1); 21072339Sabial } 21172339Sabial } else 21272339Sabial f = 0; 21372339Sabial next(remap(f)); 21472339Sabial return(0); 21572339Sabial} 21672339Sabial 21772339Sabialvoid 21872339Sabialonecommand() 21972339Sabial{ 22072339Sabial register i; 22172339Sabial jmp_buf m1; 22272339Sabial 22372339Sabial while (e.oenv) 22472339Sabial quitenv(); 22572339Sabial areanum = 1; 22672339Sabial freehere(areanum); 22772339Sabial freearea(areanum); 22872339Sabial garbage(); 22972339Sabial wdlist = 0; 23072339Sabial iolist = 0; 23172339Sabial e.errpt = 0; 23272339Sabial e.linep = line; 23372339Sabial yynerrs = 0; 23472339Sabial multiline = 0; 23572339Sabial inparse = 1; 23672339Sabial intr = 0; 23772339Sabial execflg = 0; 23872339Sabial setjmp(failpt = m1); /* Bruce Evans' fix */ 23972339Sabial if (setjmp(failpt = m1) || yyparse() || intr) { 24072339Sabial while (e.oenv) 24172339Sabial quitenv(); 24272339Sabial scraphere(); 24372339Sabial if (!talking && intr) 24472339Sabial leave(); 24572339Sabial inparse = 0; 24672339Sabial intr = 0; 24772339Sabial return; 24872339Sabial } 24972339Sabial inparse = 0; 25072339Sabial brklist = 0; 25172339Sabial intr = 0; 25272339Sabial execflg = 0; 25372339Sabial if (!flag['n']) 25472339Sabial execute(outtree, NOPIPE, NOPIPE, 0); 25572339Sabial if (!talking && intr) { 25672339Sabial execflg = 0; 25772339Sabial leave(); 25872339Sabial } 25972339Sabial if ((i = trapset) != 0) { 26072339Sabial trapset = 0; 26172339Sabial runtrap(i); 26272339Sabial } 26372339Sabial} 26472339Sabial 26572339Sabialvoid 26672339Sabialfail() 26772339Sabial{ 26872339Sabial longjmp(failpt, 1); 26972339Sabial /* NOTREACHED */ 27072339Sabial} 27172339Sabial 27272339Sabialvoid 27372339Sabialleave() 27472339Sabial{ 27572339Sabial if (execflg) 27672339Sabial fail(); 27772339Sabial scraphere(); 27872339Sabial freehere(1); 27972339Sabial runtrap(0); 28072339Sabial exit(exstat); 28172339Sabial /* NOTREACHED */ 28272339Sabial} 28372339Sabial 28472339Sabialvoid 28572339Sabialwarn(s) 28672339Sabialregister char *s; 28772339Sabial{ 28872339Sabial if(*s) { 28972339Sabial prs(s); 29072339Sabial exstat = -1; 29172339Sabial } 29272339Sabial prs("\n"); 29372339Sabial if (flag['e']) 29472339Sabial leave(); 29572339Sabial} 29672339Sabial 29772339Sabialvoid 29872339Sabialerr(s) 29972339Sabialchar *s; 30072339Sabial{ 30172339Sabial warn(s); 30272339Sabial if (flag['n']) 30372339Sabial return; 30472339Sabial if (!talking) 30572339Sabial leave(); 30672339Sabial if (e.errpt) 30772339Sabial longjmp(e.errpt, 1); 30872339Sabial closeall(); 30972339Sabial e.iop = e.iobase = iostack; 31072339Sabial} 31172339Sabial 31272339Sabialint 31372339Sabialnewenv(f) 31472339Sabialint f; 31572339Sabial{ 31672339Sabial register struct env *ep; 31772339Sabial 31872339Sabial if (f) { 31972339Sabial quitenv(); 32072339Sabial return(1); 32172339Sabial } 32272339Sabial ep = (struct env *) space(sizeof(*ep)); 32372339Sabial if (ep == NULL) { 32472339Sabial while (e.oenv) 32572339Sabial quitenv(); 32672339Sabial fail(); 32772339Sabial } 32872339Sabial *ep = e; 32972339Sabial e.oenv = ep; 33072339Sabial e.errpt = errpt; 33172339Sabial return(0); 33272339Sabial} 33372339Sabial 33472339Sabialvoid 33572339Sabialquitenv() 33672339Sabial{ 33772339Sabial register struct env *ep; 33872339Sabial register fd; 33972339Sabial 34072339Sabial if ((ep = e.oenv) != NULL) { 34172339Sabial fd = e.iofd; 34272339Sabial e = *ep; 34372339Sabial /* should close `'d files */ 34472339Sabial DELETE(ep); 34572339Sabial while (--fd >= e.iofd) 34672339Sabial close(fd); 34772339Sabial } 34872339Sabial} 34972339Sabial 35072339Sabial/* 35172339Sabial * Is any character from s1 in s2? 35272339Sabial */ 35372339Sabialint 35472339Sabialanys(s1, s2) 35572339Sabialregister char *s1, *s2; 35672339Sabial{ 35772339Sabial while (*s1) 35872339Sabial if (any(*s1++, s2)) 35972339Sabial return(1); 36072339Sabial return(0); 36172339Sabial} 36272339Sabial 36372339Sabial/* 36472339Sabial * Is character c in s? 36572339Sabial */ 36672339Sabialint 36772339Sabialany(c, s) 36872339Sabialregister int c; 36972339Sabialregister char *s; 37072339Sabial{ 37172339Sabial while (*s) 37272339Sabial if (*s++ == c) 37372339Sabial return(1); 37472339Sabial return(0); 37572339Sabial} 37672339Sabial 37772339Sabialchar * 37872339Sabialputn(n) 37972339Sabialregister int n; 38072339Sabial{ 38172339Sabial return(itoa(n, -1)); 38272339Sabial} 38372339Sabial 38472339Sabialchar * 38572339Sabialitoa(u, n) 38672339Sabialregister unsigned u; 38772339Sabialint n; 38872339Sabial{ 38972339Sabial register char *cp; 39072339Sabial static char s[20]; 39172339Sabial int m; 39272339Sabial 39372339Sabial m = 0; 39472339Sabial if (n < 0 && (int) u < 0) { 39572339Sabial m++; 39672339Sabial u = -u; 39772339Sabial } 39872339Sabial cp = s+sizeof(s); 39972339Sabial *--cp = 0; 40072339Sabial do { 40172339Sabial *--cp = u%10 + '0'; 40272339Sabial u /= 10; 40372339Sabial } while (--n > 0 || u); 40472339Sabial if (m) 40572339Sabial *--cp = '-'; 40672339Sabial return(cp); 40772339Sabial} 40872339Sabial 40972339Sabialvoid 41072339Sabialnext(f) 41172339Sabialint f; 41272339Sabial{ 41372339Sabial PUSHIO(afile, f, filechar); 41472339Sabial} 41572339Sabial 41672339Sabialvoid 41772339Sabialonintr(s) 41872339Sabialint s; /* ANSI C requires a parameter */ 41972339Sabial{ 42072339Sabial signal(SIGINT, onintr); 42172339Sabial intr = 1; 42272339Sabial if (talking) { 42372339Sabial if (inparse) { 42472339Sabial prs("\n"); 42572339Sabial fail(); 42672339Sabial } 42772339Sabial } 42872339Sabial else if (heedint) { 42972339Sabial execflg = 0; 43072339Sabial leave(); 43172339Sabial } 43272339Sabial} 43372339Sabial 43472339Sabialint 43572339Sabialletter(c) 43672339Sabialregister c; 43772339Sabial{ 43872339Sabial return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'); 43972339Sabial} 44072339Sabial 44172339Sabialint 44272339Sabialdigit(c) 44372339Sabialregister c; 44472339Sabial{ 44572339Sabial return(c >= '0' && c <= '9'); 44672339Sabial} 44772339Sabial 44872339Sabialint 44972339Sabialletnum(c) 45072339Sabialregister c; 45172339Sabial{ 45272339Sabial return(letter(c) || digit(c)); 45372339Sabial} 45472339Sabial 45572339Sabialchar * 45672339Sabialspace(n) 45772339Sabialint n; 45872339Sabial{ 45972339Sabial register char *cp; 46072339Sabial 46172339Sabial if ((cp = getcell(n)) == 0) 46272339Sabial err("out of string space"); 46372339Sabial return(cp); 46472339Sabial} 46572339Sabial 46672339Sabialchar * 46772339Sabialstrsave(s, a) 46872339Sabialregister char *s; 46972339Sabialint a; 47072339Sabial{ 47172339Sabial register char *cp, *xp; 47272339Sabial 47372339Sabial if ((cp = space(strlen(s)+1)) != NULL) { 47472339Sabial setarea((char *)cp, a); 47572339Sabial for (xp = cp; (*xp++ = *s++) != '\0';) 47672339Sabial ; 47772339Sabial return(cp); 47872339Sabial } 47972339Sabial return(""); 48072339Sabial} 48172339Sabial 48272339Sabialvoid 48372339Sabialxfree(s) 48472339Sabialregister char *s; 48572339Sabial{ 48672339Sabial DELETE(s); 48772339Sabial} 48872339Sabial 48972339Sabial/* 49072339Sabial * trap handling 49172339Sabial */ 49272339Sabialvoid 49372339Sabialsig(i) 49472339Sabialregister int i; 49572339Sabial{ 49672339Sabial trapset = i; 49772339Sabial signal(i, sig); 49872339Sabial} 49972339Sabial 50072339Sabialvoid runtrap(i) 50172339Sabialint i; 50272339Sabial{ 50372339Sabial char *trapstr; 50472339Sabial 50572339Sabial if ((trapstr = trap[i]) == NULL) 50672339Sabial return; 50772339Sabial if (i == 0) 50872339Sabial trap[i] = 0; 50972339Sabial RUN(aword, trapstr, nlchar); 51072339Sabial} 51172339Sabial 51272339Sabial/* -------- var.c -------- */ 51372339Sabial/* #include "sh.h" */ 51472339Sabial 51572339Sabial/* 51672339Sabial * Find the given name in the dictionary 51772339Sabial * and return its value. If the name was 51872339Sabial * not previously there, enter it now and 51972339Sabial * return a null value. 52072339Sabial */ 52172339Sabialstruct var * 52272339Sabiallookup(n) 52372339Sabialregister char *n; 52472339Sabial{ 52572339Sabial register struct var *vp; 52672339Sabial register char *cp; 52772339Sabial register int c; 52872339Sabial static struct var dummy; 52972339Sabial 53072339Sabial if (digit(*n)) { 53172339Sabial dummy.name = n; 53272339Sabial for (c = 0; digit(*n) && c < 1000; n++) 53372339Sabial c = c*10 + *n-'0'; 53472339Sabial dummy.status = RONLY; 53572339Sabial dummy.value = c <= dolc? dolv[c]: null; 53672339Sabial return(&dummy); 53772339Sabial } 53872339Sabial for (vp = vlist; vp; vp = vp->next) 53972339Sabial if (eqname(vp->name, n)) 54072339Sabial return(vp); 54172339Sabial cp = findeq(n); 54272339Sabial vp = (struct var *)space(sizeof(*vp)); 54372339Sabial if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) { 54472339Sabial dummy.name = dummy.value = ""; 54572339Sabial return(&dummy); 54672339Sabial } 54772339Sabial for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++) 54872339Sabial ; 54972339Sabial if (*cp == 0) 55072339Sabial *cp = '='; 55172339Sabial *++cp = 0; 55272339Sabial setarea((char *)vp, 0); 55372339Sabial setarea((char *)vp->name, 0); 55472339Sabial vp->value = null; 55572339Sabial vp->next = vlist; 55672339Sabial vp->status = GETCELL; 55772339Sabial vlist = vp; 55872339Sabial return(vp); 55972339Sabial} 56072339Sabial 56172339Sabial/* 56272339Sabial * give variable at `vp' the value `val'. 56372339Sabial */ 56472339Sabialvoid 56572339Sabialsetval(vp, val) 56672339Sabialstruct var *vp; 56772339Sabialchar *val; 56872339Sabial{ 56972339Sabial nameval(vp, val, (char *)NULL); 57072339Sabial} 57172339Sabial 57272339Sabial/* 57372339Sabial * if name is not NULL, it must be 57472339Sabial * a prefix of the space `val', 57572339Sabial * and end with `='. 57672339Sabial * this is all so that exporting 57772339Sabial * values is reasonably painless. 57872339Sabial */ 57972339Sabialvoid 58072339Sabialnameval(vp, val, name) 58172339Sabialregister struct var *vp; 58272339Sabialchar *val, *name; 58372339Sabial{ 58472339Sabial register char *cp, *xp; 58572339Sabial char *nv; 58672339Sabial int fl; 58772339Sabial 58872339Sabial if (vp->status & RONLY) { 58972339Sabial for (xp = vp->name; *xp && *xp != '=';) 59072339Sabial putc(*xp++); 59172339Sabial err(" is read-only"); 59272339Sabial return; 59372339Sabial } 59472339Sabial fl = 0; 59572339Sabial if (name == NULL) { 59672339Sabial xp = space(strlen(vp->name)+strlen(val)+2); 59772339Sabial if (xp == 0) 59872339Sabial return; 59972339Sabial /* make string: name=value */ 60072339Sabial setarea((char *)xp, 0); 60172339Sabial name = xp; 60272339Sabial for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++) 60372339Sabial ; 60472339Sabial if (*xp++ == 0) 60572339Sabial xp[-1] = '='; 60672339Sabial nv = xp; 60772339Sabial for (cp = val; (*xp++ = *cp++) != '\0';) 60872339Sabial ; 60972339Sabial val = nv; 61072339Sabial fl = GETCELL; 61172339Sabial } 61272339Sabial if (vp->status & GETCELL) 61372339Sabial xfree(vp->name); /* form new string `name=value' */ 61472339Sabial vp->name = name; 61572339Sabial vp->value = val; 61672339Sabial vp->status |= fl; 61772339Sabial} 61872339Sabial 61972339Sabialvoid 62072339Sabialexport(vp) 62172339Sabialstruct var *vp; 62272339Sabial{ 62372339Sabial vp->status |= EXPORT; 62472339Sabial} 62572339Sabial 62672339Sabialvoid 62772339Sabialronly(vp) 62872339Sabialstruct var *vp; 62972339Sabial{ 63072339Sabial if (letter(vp->name[0])) /* not an internal symbol ($# etc) */ 63172339Sabial vp->status |= RONLY; 63272339Sabial} 63372339Sabial 63472339Sabialint 63572339Sabialisassign(s) 63672339Sabialregister char *s; 63772339Sabial{ 63872339Sabial if (!letter((int)*s)) 63972339Sabial return(0); 64072339Sabial for (; *s != '='; s++) 64172339Sabial if (*s == 0 || !letnum(*s)) 64272339Sabial return(0); 64372339Sabial return(1); 64472339Sabial} 64572339Sabial 64672339Sabialint 64772339Sabialassign(s, cf) 64872339Sabialregister char *s; 64972339Sabialint cf; 65072339Sabial{ 65172339Sabial register char *cp; 65272339Sabial struct var *vp; 65372339Sabial 65472339Sabial if (!letter(*s)) 65572339Sabial return(0); 65672339Sabial for (cp = s; *cp != '='; cp++) 65772339Sabial if (*cp == 0 || !letnum(*cp)) 65872339Sabial return(0); 65972339Sabial vp = lookup(s); 66072339Sabial nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); 66172339Sabial if (cf != COPYV) 66272339Sabial vp->status &= ~GETCELL; 66372339Sabial return(1); 66472339Sabial} 66572339Sabial 66672339Sabialint 66772339Sabialcheckname(cp) 66872339Sabialregister char *cp; 66972339Sabial{ 67072339Sabial if (!letter(*cp++)) 67172339Sabial return(0); 67272339Sabial while (*cp) 67372339Sabial if (!letnum(*cp++)) 67472339Sabial return(0); 67572339Sabial return(1); 67672339Sabial} 67772339Sabial 67872339Sabialvoid 67972339Sabialputvlist(f, out) 68072339Sabialregister int f, out; 68172339Sabial{ 68272339Sabial register struct var *vp; 68372339Sabial 68472339Sabial for (vp = vlist; vp; vp = vp->next) 68572339Sabial if (vp->status & f && letter(*vp->name)) { 68672339Sabial if (vp->status & EXPORT) 68772339Sabial write(out, "export ", 7); 68872339Sabial if (vp->status & RONLY) 68972339Sabial write(out, "readonly ", 9); 69072339Sabial write(out, vp->name, (int)(findeq(vp->name) - vp->name)); 69172339Sabial write(out, "\n", 1); 69272339Sabial } 69372339Sabial} 69472339Sabial 69572339Sabialint 69672339Sabialeqname(n1, n2) 69772339Sabialregister char *n1, *n2; 69872339Sabial{ 69972339Sabial for (; *n1 != '=' && *n1 != 0; n1++) 70072339Sabial if (*n2++ != *n1) 70172339Sabial return(0); 70272339Sabial return(*n2 == 0 || *n2 == '='); 70372339Sabial} 70472339Sabial 70572339Sabialstatic char * 70672339Sabialfindeq(cp) 70772339Sabialregister char *cp; 70872339Sabial{ 70972339Sabial while (*cp != '\0' && *cp != '=') 71072339Sabial cp++; 71172339Sabial return(cp); 71272339Sabial} 71372339Sabial 71472339Sabial/* -------- gmatch.c -------- */ 71572339Sabial/* 71672339Sabial * int gmatch(string, pattern) 71772339Sabial * char *string, *pattern; 71872339Sabial * 71972339Sabial * Match a pattern as in sh(1). 72072339Sabial */ 72172339Sabial 72272339Sabial#define CMASK 0377 72372339Sabial#define QUOTE 0200 72472339Sabial#define QMASK (CMASK&~QUOTE) 72572339Sabial#define NOT '!' /* might use ^ */ 72672339Sabial 72772339Sabialint 72872339Sabialgmatch(s, p) 72972339Sabialregister char *s, *p; 73072339Sabial{ 73172339Sabial register int sc, pc; 73272339Sabial 73372339Sabial if (s == NULL || p == NULL) 73472339Sabial return(0); 73572339Sabial while ((pc = *p++ & CMASK) != '\0') { 73672339Sabial sc = *s++ & QMASK; 73772339Sabial switch (pc) { 73872339Sabial case '[': 73972339Sabial if ((p = cclass(p, sc)) == NULL) 74072339Sabial return(0); 74172339Sabial break; 74272339Sabial 74372339Sabial case '?': 74472339Sabial if (sc == 0) 74572339Sabial return(0); 74672339Sabial break; 74772339Sabial 74872339Sabial case '*': 74972339Sabial s--; 75072339Sabial do { 75172339Sabial if (*p == '\0' || gmatch(s, p)) 75272339Sabial return(1); 75372339Sabial } while (*s++ != '\0'); 75472339Sabial return(0); 75572339Sabial 75672339Sabial default: 75772339Sabial if (sc != (pc&~QUOTE)) 75872339Sabial return(0); 75972339Sabial } 76072339Sabial } 76172339Sabial return(*s == 0); 76272339Sabial} 76372339Sabial 76472339Sabialstatic char * 76572339Sabialcclass(p, sub) 76672339Sabialregister char *p; 76772339Sabialregister int sub; 76872339Sabial{ 76972339Sabial register int c, d, not, found; 77072339Sabial 77172339Sabial if ((not = *p == NOT) != 0) 77272339Sabial p++; 77372339Sabial found = not; 77472339Sabial do { 77572339Sabial if (*p == '\0') 77672339Sabial return((char *)NULL); 77772339Sabial c = *p & CMASK; 77872339Sabial if (p[1] == '-' && p[2] != ']') { 77972339Sabial d = p[2] & CMASK; 78072339Sabial p++; 78172339Sabial } else 78272339Sabial d = c; 78372339Sabial if (c == sub || (c <= sub && sub <= d)) 78472339Sabial found = !not; 78572339Sabial } while (*++p != ']'); 78672339Sabial return(found? p+1: (char *)NULL); 78772339Sabial} 78872339Sabial 78972339Sabial/* -------- area.c -------- */ 79072339Sabial#define REGSIZE sizeof(struct region) 79172339Sabial#define GROWBY 256 79272339Sabial#undef SHRINKBY 64 79372339Sabial#define FREE 32767 79472339Sabial#define BUSY 0 79572339Sabial#define ALIGN (sizeof(int)-1) 79672339Sabial 79772339Sabial/* #include "area.h" */ 79872339Sabial 79972339Sabialstruct region { 80072339Sabial struct region *next; 80172339Sabial int area; 80272339Sabial}; 80372339Sabial 80472339Sabial/* 80572339Sabial * All memory between (char *)areabot and (char *)(areatop+1) is 80672339Sabial * exclusively administered by the area management routines. 80772339Sabial * It is assumed that sbrk() and brk() manipulate the high end. 80872339Sabial */ 80972339Sabialstatic struct region *areabot; /* bottom of area */ 81072339Sabialstatic struct region *areatop; /* top of area */ 81172339Sabialstatic struct region *areanxt; /* starting point of scan */ 81272339Sabial 81372339Sabialvoid 81472339Sabialinitarea() 81572339Sabial{ 81672339Sabial while ((int)sbrk(0) & ALIGN) 81772339Sabial sbrk(1); 81872339Sabial areabot = (struct region *)sbrk(REGSIZE); 81972339Sabial areabot->next = areabot; 82072339Sabial areabot->area = BUSY; 82172339Sabial areatop = areabot; 82272339Sabial areanxt = areabot; 82372339Sabial} 82472339Sabial 82572339Sabialchar * 82672339Sabialgetcell(nbytes) 82772339Sabialunsigned nbytes; 82872339Sabial{ 82972339Sabial register int nregio; 83072339Sabial register struct region *p, *q; 83172339Sabial register i; 83272339Sabial 83372339Sabial if (nbytes == 0) 83472339Sabial abort(); /* silly and defeats the algorithm */ 83572339Sabial /* 83672339Sabial * round upwards and add administration area 83772339Sabial */ 83872339Sabial nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1; 83972339Sabial for (p = areanxt;;) { 84072339Sabial if (p->area > areanum) { 84172339Sabial /* 84272339Sabial * merge free cells 84372339Sabial */ 84472339Sabial while ((q = p->next)->area > areanum && q != areanxt) 84572339Sabial p->next = q->next; 84672339Sabial /* 84772339Sabial * exit loop if cell big enough 84872339Sabial */ 84972339Sabial if (q >= p + nregio) 85072339Sabial goto found; 85172339Sabial } 85272339Sabial p = p->next; 85372339Sabial if (p == areanxt) 85472339Sabial break; 85572339Sabial } 85672339Sabial i = nregio >= GROWBY ? nregio : GROWBY; 85772339Sabial p = (struct region *)sbrk(i * REGSIZE); 85872339Sabial if (p == (struct region *)-1) 85972339Sabial return((char *)NULL); 86072339Sabial p--; 86172339Sabial if (p != areatop) 86272339Sabial abort(); /* allocated areas are contiguous */ 86372339Sabial q = p + i; 86472339Sabial p->next = q; 86572339Sabial p->area = FREE; 86672339Sabial q->next = areabot; 86772339Sabial q->area = BUSY; 86872339Sabial areatop = q; 86972339Sabialfound: 87072339Sabial /* 87172339Sabial * we found a FREE area big enough, pointed to by 'p', and up to 'q' 87272339Sabial */ 87372339Sabial areanxt = p + nregio; 87472339Sabial if (areanxt < q) { 87572339Sabial /* 87672339Sabial * split into requested area and rest 87772339Sabial */ 87872339Sabial if (areanxt+1 > q) 87972339Sabial abort(); /* insufficient space left for admin */ 88072339Sabial areanxt->next = q; 88172339Sabial areanxt->area = FREE; 88272339Sabial p->next = areanxt; 88372339Sabial } 88472339Sabial p->area = areanum; 88572339Sabial return((char *)(p+1)); 88672339Sabial} 88772339Sabial 88872339Sabialvoid 88972339Sabialfreecell(cp) 89072339Sabialchar *cp; 89172339Sabial{ 89272339Sabial register struct region *p; 89372339Sabial 89472339Sabial if ((p = (struct region *)cp) != NULL) { 89572339Sabial p--; 89672339Sabial if (p < areanxt) 89772339Sabial areanxt = p; 89872339Sabial p->area = FREE; 89972339Sabial } 90072339Sabial} 90172339Sabial 90272339Sabialvoid 90372339Sabialfreearea(a) 90472339Sabialregister int a; 90572339Sabial{ 90672339Sabial register struct region *p, *top; 90772339Sabial 90872339Sabial top = areatop; 90972339Sabial for (p = areabot; p != top; p = p->next) 91072339Sabial if (p->area >= a) 91172339Sabial p->area = FREE; 91272339Sabial} 91372339Sabial 91472339Sabialvoid 91572339Sabialsetarea(cp,a) 91672339Sabialchar *cp; 91772339Sabialint a; 91872339Sabial{ 91972339Sabial register struct region *p; 92072339Sabial 92172339Sabial if ((p = (struct region *)cp) != NULL) 92272339Sabial (p-1)->area = a; 92372339Sabial} 92472339Sabial 92572339Sabialint 92672339Sabialgetarea(cp) 92772339Sabialchar *cp; 92872339Sabial{ 92972339Sabial return ((struct region*)cp-1)->area; 93072339Sabial} 93172339Sabial 93272339Sabialvoid 93372339Sabialgarbage() 93472339Sabial{ 93572339Sabial register struct region *p, *q, *top; 93672339Sabial 93772339Sabial top = areatop; 93872339Sabial for (p = areabot; p != top; p = p->next) { 93972339Sabial if (p->area > areanum) { 94072339Sabial while ((q = p->next)->area > areanum) 94172339Sabial p->next = q->next; 94272339Sabial areanxt = p; 94372339Sabial } 94472339Sabial } 94572339Sabial#ifdef SHRINKBY 94672339Sabial if (areatop >= q + SHRINKBY && q->area > areanum) { 94772339Sabial brk((char *)(q+1)); 94872339Sabial q->next = areabot; 94972339Sabial q->area = BUSY; 95072339Sabial areatop = q; 95172339Sabial } 95272339Sabial#endif 95372339Sabial} 954