139213Sgibbs#define Extern extern 239213Sgibbs#include <sys/types.h> 339213Sgibbs#include <signal.h> 439213Sgibbs#define _NSIG NSIG 539213Sgibbs#include <errno.h> 639213Sgibbs#include <setjmp.h> 739213Sgibbs#include "sh.h" 839213Sgibbs/* -------- sh.c -------- */ 939213Sgibbs/* 1039213Sgibbs * shell 1139213Sgibbs */ 1239213Sgibbs 1339213Sgibbs/* #include "sh.h" */ 1439213Sgibbs 1539213Sgibbsint intr; 1639213Sgibbsint inparse; 1739213Sgibbschar flags['z'-'a'+1]; 1839213Sgibbschar *flag = flags-'a'; 1939213Sgibbschar *elinep = line+sizeof(line)-5; 2039213Sgibbschar *null = ""; 2139213Sgibbsint heedint =1; 2239213Sgibbsstruct env e ={line, iostack, iostack-1, 2339213Sgibbs (xint *)NULL, FDBASE, (struct env *)NULL}; 2439213Sgibbs 2539213Sgibbsextern char **environ; /* environment pointer */ 2639213Sgibbs 2739213Sgibbs/* 2850477Speter * default shell, search rules 2939213Sgibbs */ 3039213Sgibbschar shellname[] = "/bin/sh"; 3139213Sgibbschar search[] = ":/bin:/usr/bin"; 3239213Sgibbs 3339213Sgibbs_PROTOTYPE(void (*qflag), (int)) = SIG_IGN; 3439213Sgibbs 3539213Sgibbs_PROTOTYPE(int main, (int argc, char **argv )); 3660041Sphk_PROTOTYPE(int newfile, (char *s )); 3739213Sgibbs_PROTOTYPE(static char *findeq, (char *cp )); 3839213Sgibbs_PROTOTYPE(static char *cclass, (char *p, int sub )); 3939213Sgibbs_PROTOTYPE(void initarea, (void)); 4050073Sken 4139213Sgibbsint main(argc, argv) 4239213Sgibbsint argc; 4339213Sgibbsregister char **argv; 4439213Sgibbs{ 4539213Sgibbs register int f; 4639213Sgibbs register char *s; 4739213Sgibbs int cflag; 4839213Sgibbs char *name, **ap; 4939213Sgibbs int (*iof)(); 5039213Sgibbs 5139213Sgibbs initarea(); 5239213Sgibbs if ((ap = environ) != NULL) { 5350073Sken while (*ap) 5450073Sken assign(*ap++, !COPYV); 5539213Sgibbs for (ap = environ; *ap;) 5639213Sgibbs export(lookup(*ap++)); 5739213Sgibbs } 5839213Sgibbs closeall(); 5939213Sgibbs areanum = 1; 6039213Sgibbs 6139213Sgibbs shell = lookup("SHELL"); 6239213Sgibbs if (shell->value == null) 6339213Sgibbs setval(shell, shellname); 6439213Sgibbs export(shell); 6539213Sgibbs 6639213Sgibbs homedir = lookup("HOME"); 6739213Sgibbs if (homedir->value == null) 6839213Sgibbs setval(homedir, "/"); 6939213Sgibbs export(homedir); 7039213Sgibbs 7139213Sgibbs setval(lookup("$"), itoa(getpid(), 5)); 7239213Sgibbs 7339213Sgibbs path = lookup("PATH"); 7439213Sgibbs if (path->value == null) 7539213Sgibbs setval(path, search); 7639213Sgibbs export(path); 7739213Sgibbs 7839213Sgibbs ifs = lookup("IFS"); 7959249Sphk if (ifs->value == null) 8039213Sgibbs setval(ifs, " \t\n"); 8160938Sjake 8239213Sgibbs prompt = lookup("PS1"); 8339213Sgibbs if (prompt->value == null) 8439213Sgibbs#ifndef UNIXSHELL 8550073Sken setval(prompt, "$ "); 8653257Sken#else 8739213Sgibbs setval(prompt, "% "); 8839213Sgibbs#endif 8939213Sgibbs 9039213Sgibbs if (geteuid() == 0) { 9139213Sgibbs setval(prompt, "# "); 9239213Sgibbs prompt->status &= ~EXPORT; 9339213Sgibbs } 9439213Sgibbs cprompt = lookup("PS2"); 9539213Sgibbs if (cprompt->value == null) 9640603Sken setval(cprompt, "> "); 9739213Sgibbs 9839213Sgibbs iof = filechar; 9939213Sgibbs cflag = 0; 10039213Sgibbs name = *argv++; 10150073Sken if (--argc >= 1) { 10239213Sgibbs if(argv[0][0] == '-' && argv[0][1] != '\0') { 10339213Sgibbs for (s = argv[0]+1; *s; s++) 10439213Sgibbs switch (*s) { 10539213Sgibbs case 'c': 10639213Sgibbs prompt->status &= ~EXPORT; 10739213Sgibbs cprompt->status &= ~EXPORT; 10839213Sgibbs setval(prompt, ""); 10939213Sgibbs setval(cprompt, ""); 11039213Sgibbs cflag = 1; 11139213Sgibbs if (--argc > 0) 11239213Sgibbs PUSHIO(aword, *++argv, iof = nlchar); 11339213Sgibbs break; 11439213Sgibbs 11539213Sgibbs case 'q': 11639213Sgibbs qflag = SIG_DFL; 11739213Sgibbs break; 11839213Sgibbs 11939213Sgibbs case 's': 12039213Sgibbs /* standard input */ 12147625Sphk break; 12247625Sphk 12347625Sphk case 't': 12447625Sphk prompt->status &= ~EXPORT; 12547625Sphk setval(prompt, ""); 12650073Sken iof = linechar; 12747625Sphk break; 12847625Sphk 12947625Sphk case 'i': 13047625Sphk talking++; 13147625Sphk default: 13247625Sphk if (*s>='a' && *s<='z') 13347625Sphk flag[*s]++; 13447625Sphk } 13547625Sphk } else { 13639213Sgibbs argv--; 13739213Sgibbs argc++; 13839213Sgibbs } 13939213Sgibbs if (iof == filechar && --argc > 0) { 14050073Sken setval(prompt, ""); 14150073Sken setval(cprompt, ""); 14250073Sken prompt->status &= ~EXPORT; 14350073Sken cprompt->status &= ~EXPORT; 14439213Sgibbs if (newfile(name = *++argv)) 14539213Sgibbs exit(1); 14639213Sgibbs } 14739213Sgibbs } 14839213Sgibbs setdash(); 14939213Sgibbs if (e.iop < iostack) { 15039213Sgibbs PUSHIO(afile, 0, iof); 15140603Sken if (isatty(0) && isatty(1) && !cflag) 15239213Sgibbs talking++; 15339213Sgibbs } 15439213Sgibbs signal(SIGQUIT, qflag); 15539213Sgibbs if (name && name[0] == '-') { 15639213Sgibbs talking++; 15739213Sgibbs if ((f = open(".profile", 0)) >= 0) 15839213Sgibbs next(remap(f)); 15939213Sgibbs if ((f = open("/etc/profile", 0)) >= 0) 16040603Sken next(remap(f)); 16140603Sken } 16240603Sken if (talking) 16340603Sken signal(SIGTERM, sig); 16440603Sken if (signal(SIGINT, SIG_IGN) != SIG_IGN) 16540603Sken signal(SIGINT, onintr); 16639213Sgibbs dolv = argv; 16749982Sbillf dolc = argc; 16839213Sgibbs dolv[0] = name; 16941297Sken if (dolc > 1) 17041297Sken for (ap = ++argv; --argc > 0;) 17139213Sgibbs if (assign(*ap = *argv++, !COPYV)) 17241297Sken dolc--; /* keyword */ 17339213Sgibbs else 17441297Sken ap++; 17541297Sken setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); 17639213Sgibbs 17739213Sgibbs for (;;) { 17839213Sgibbs if (talking && e.iop <= iostack) 17939213Sgibbs prs(prompt->value); 18039213Sgibbs onecommand(); 18139213Sgibbs } 18239213Sgibbs} 18339213Sgibbs 18439213Sgibbsvoid 18539213Sgibbssetdash() 18639213Sgibbs{ 18739213Sgibbs register char *cp, c; 18839213Sgibbs char m['z'-'a'+1]; 18939213Sgibbs 19039213Sgibbs cp = m; 19139213Sgibbs for (c='a'; c<='z'; c++) 19239213Sgibbs if (flag[c]) 19339213Sgibbs *cp++ = c; 19439213Sgibbs *cp = 0; 19539213Sgibbs setval(lookup("-"), m); 19639213Sgibbs} 19739213Sgibbs 19839213Sgibbsint 19939213Sgibbsnewfile(s) 20039213Sgibbsregister char *s; 20139213Sgibbs{ 20239213Sgibbs register f; 20339213Sgibbs 20439213Sgibbs if (strcmp(s, "-") != 0) { 20539213Sgibbs f = open(s, 0); 20639213Sgibbs if (f < 0) { 20739213Sgibbs prs(s); 20839213Sgibbs err(": cannot open"); 20939213Sgibbs return(1); 21039213Sgibbs } 21139213Sgibbs } else 21239213Sgibbs f = 0; 21339213Sgibbs next(remap(f)); 21439213Sgibbs return(0); 21539213Sgibbs} 21639213Sgibbs 21739213Sgibbsvoid 21859249Sphkonecommand() 21939213Sgibbs{ 22039213Sgibbs register i; 22139213Sgibbs jmp_buf m1; 22239213Sgibbs 22339213Sgibbs while (e.oenv) 22439213Sgibbs quitenv(); 22559249Sphk areanum = 1; 22639213Sgibbs freehere(areanum); 22739213Sgibbs freearea(areanum); 22859249Sphk garbage(); 22939213Sgibbs wdlist = 0; 23039213Sgibbs iolist = 0; 23139213Sgibbs e.errpt = 0; 23239213Sgibbs e.linep = line; 23339213Sgibbs yynerrs = 0; 23439213Sgibbs multiline = 0; 23539213Sgibbs inparse = 1; 23639213Sgibbs intr = 0; 23739213Sgibbs execflg = 0; 23839213Sgibbs setjmp(failpt = m1); /* Bruce Evans' fix */ 23939213Sgibbs if (setjmp(failpt = m1) || yyparse() || intr) { 24039213Sgibbs while (e.oenv) 24139213Sgibbs quitenv(); 24239213Sgibbs scraphere(); 24339213Sgibbs if (!talking && intr) 24439213Sgibbs leave(); 24559249Sphk inparse = 0; 24639213Sgibbs intr = 0; 24739213Sgibbs return; 24839213Sgibbs } 24939213Sgibbs inparse = 0; 25039213Sgibbs brklist = 0; 25139213Sgibbs intr = 0; 25259249Sphk execflg = 0; 25339213Sgibbs if (!flag['n']) 25439213Sgibbs execute(outtree, NOPIPE, NOPIPE, 0); 25539213Sgibbs if (!talking && intr) { 25639213Sgibbs execflg = 0; 25739213Sgibbs leave(); 25839213Sgibbs } 25939213Sgibbs if ((i = trapset) != 0) { 26039213Sgibbs trapset = 0; 26139213Sgibbs runtrap(i); 26239213Sgibbs } 26359249Sphk} 26439213Sgibbs 26539213Sgibbsvoid 26639213Sgibbsfail() 26739213Sgibbs{ 26859249Sphk longjmp(failpt, 1); 26939213Sgibbs /* NOTREACHED */ 27039213Sgibbs} 27139213Sgibbs 27239213Sgibbsvoid 27339213Sgibbsleave() 27439213Sgibbs{ 27539213Sgibbs if (execflg) 27639213Sgibbs fail(); 27739213Sgibbs scraphere(); 27839213Sgibbs freehere(1); 27939213Sgibbs runtrap(0); 28039213Sgibbs exit(exstat); 28139213Sgibbs /* NOTREACHED */ 28239213Sgibbs} 28339213Sgibbs 28439213Sgibbsvoid 28539213Sgibbswarn(s) 28639213Sgibbsregister char *s; 28739213Sgibbs{ 28839213Sgibbs if(*s) { 28939213Sgibbs prs(s); 29039213Sgibbs exstat = -1; 29139213Sgibbs } 29239213Sgibbs prs("\n"); 29339213Sgibbs if (flag['e']) 29439213Sgibbs leave(); 29539213Sgibbs} 29639213Sgibbs 29739213Sgibbsvoid 29839213Sgibbserr(s) 29939213Sgibbschar *s; 30039213Sgibbs{ 30139213Sgibbs warn(s); 30239213Sgibbs if (flag['n']) 30339213Sgibbs return; 30439213Sgibbs if (!talking) 30539213Sgibbs leave(); 30639213Sgibbs if (e.errpt) 30739213Sgibbs longjmp(e.errpt, 1); 30839213Sgibbs closeall(); 30939213Sgibbs e.iop = e.iobase = iostack; 31039213Sgibbs} 31139213Sgibbs 31239213Sgibbsint 31339213Sgibbsnewenv(f) 31439213Sgibbsint f; 31539213Sgibbs{ 31639213Sgibbs register struct env *ep; 31739213Sgibbs 31839213Sgibbs if (f) { 31939213Sgibbs quitenv(); 32039213Sgibbs return(1); 32139213Sgibbs } 32239213Sgibbs ep = (struct env *) space(sizeof(*ep)); 32339213Sgibbs if (ep == NULL) { 32439213Sgibbs while (e.oenv) 32539213Sgibbs quitenv(); 32639213Sgibbs fail(); 32739213Sgibbs } 32839213Sgibbs *ep = e; 32939213Sgibbs e.oenv = ep; 33039213Sgibbs e.errpt = errpt; 33139213Sgibbs return(0); 33239213Sgibbs} 33339213Sgibbs 33439213Sgibbsvoid 33539213Sgibbsquitenv() 33639213Sgibbs{ 33739213Sgibbs register struct env *ep; 33839213Sgibbs register fd; 33939213Sgibbs 34039213Sgibbs if ((ep = e.oenv) != NULL) { 34139213Sgibbs fd = e.iofd; 34259249Sphk e = *ep; 34339213Sgibbs /* should close `'d files */ 34450073Sken DELETE(ep); 34550073Sken while (--fd >= e.iofd) 34639213Sgibbs close(fd); 34739213Sgibbs } 34839213Sgibbs} 34939213Sgibbs 35039213Sgibbs/* 35139213Sgibbs * Is any character from s1 in s2? 35239213Sgibbs */ 35356148Smjacobint 35443819Skenanys(s1, s2) 35539213Sgibbsregister char *s1, *s2; 35653257Sken{ 35753257Sken while (*s1) 35853257Sken if (any(*s1++, s2)) 35939213Sgibbs return(1); 36039213Sgibbs return(0); 36139213Sgibbs} 36239213Sgibbs 36339213Sgibbs/* 36439213Sgibbs * Is character c in s? 36539213Sgibbs */ 36639213Sgibbsint 36739213Sgibbsany(c, s) 36839213Sgibbsregister int c; 36939213Sgibbsregister char *s; 37039213Sgibbs{ 37139213Sgibbs while (*s) 37239213Sgibbs if (*s++ == c) 37339213Sgibbs return(1); 37439213Sgibbs return(0); 37539213Sgibbs} 37639213Sgibbs 37739213Sgibbschar * 37839213Sgibbsputn(n) 37939213Sgibbsregister int n; 38039213Sgibbs{ 38140603Sken return(itoa(n, -1)); 38240603Sken} 38340603Sken 38440603Skenchar * 38559249Sphkitoa(u, n) 38640603Skenregister unsigned u; 38740603Skenint n; 38840603Sken{ 38940603Sken register char *cp; 39040603Sken static char s[20]; 39140603Sken int m; 39240603Sken 39340603Sken m = 0; 39440603Sken if (n < 0 && (int) u < 0) { 39540603Sken m++; 39640603Sken u = -u; 39740603Sken } 39840603Sken cp = s+sizeof(s); 39940603Sken *--cp = 0; 40040603Sken do { 40140603Sken *--cp = u%10 + '0'; 40240603Sken u /= 10; 40340603Sken } while (--n > 0 || u); 40440603Sken if (m) 40540603Sken *--cp = '-'; 40640603Sken return(cp); 40740603Sken} 40840603Sken 40940603Skenvoid 41040603Skennext(f) 41140603Skenint f; 41240603Sken{ 41340603Sken PUSHIO(afile, f, filechar); 41440603Sken} 41559249Sphk 41659249Sphkvoid 41759249Sphkonintr(s) 41859249Sphkint s; /* ANSI C requires a parameter */ 41959249Sphk{ 42040603Sken signal(SIGINT, onintr); 42140603Sken intr = 1; 42240603Sken if (talking) { 42340603Sken if (inparse) { 42440603Sken prs("\n"); 42540603Sken fail(); 42640603Sken } 42740603Sken } 42840603Sken else if (heedint) { 42940603Sken execflg = 0; 43039213Sgibbs leave(); 43139213Sgibbs } 43240603Sken} 43340603Sken 43440603Skenint 43540603Skenletter(c) 43640603Skenregister c; 43740603Sken{ 43853257Sken return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'); 43953257Sken} 44039213Sgibbs 44139213Sgibbsint 44239213Sgibbsdigit(c) 44340603Skenregister c; 44439213Sgibbs{ 44539213Sgibbs return(c >= '0' && c <= '9'); 44639213Sgibbs} 44739213Sgibbs 44839213Sgibbsint 44939213Sgibbsletnum(c) 45039213Sgibbsregister c; 45139213Sgibbs{ 45239213Sgibbs return(letter(c) || digit(c)); 45339213Sgibbs} 45439213Sgibbs 45539213Sgibbschar * 45639213Sgibbsspace(n) 45739213Sgibbsint n; 45839213Sgibbs{ 45939213Sgibbs register char *cp; 46056148Smjacob 46139213Sgibbs if ((cp = getcell(n)) == 0) 46239213Sgibbs err("out of string space"); 46339213Sgibbs return(cp); 46439213Sgibbs} 46539213Sgibbs 46639213Sgibbschar * 46739213Sgibbsstrsave(s, a) 46840603Skenregister char *s; 46940603Skenint a; 47040603Sken{ 47140603Sken register char *cp, *xp; 47239213Sgibbs 47339213Sgibbs if ((cp = space(strlen(s)+1)) != NULL) { 47439213Sgibbs setarea((char *)cp, a); 47539213Sgibbs for (xp = cp; (*xp++ = *s++) != '\0';) 47639213Sgibbs ; 47739213Sgibbs return(cp); 47839213Sgibbs } 47939213Sgibbs return(""); 48039213Sgibbs} 48139213Sgibbs 48239213Sgibbsvoid 48339213Sgibbsxfree(s) 48439213Sgibbsregister char *s; 48539213Sgibbs{ 48639213Sgibbs DELETE(s); 48739213Sgibbs} 48839213Sgibbs 48939213Sgibbs/* 49039213Sgibbs * trap handling 49139213Sgibbs */ 49239213Sgibbsvoid 49339213Sgibbssig(i) 49439213Sgibbsregister int i; 49539213Sgibbs{ 49639213Sgibbs trapset = i; 49747413Sgibbs signal(i, sig); 49839213Sgibbs} 49939213Sgibbs 50047413Sgibbsvoid runtrap(i) 50139213Sgibbsint i; 50239213Sgibbs{ 50339213Sgibbs char *trapstr; 50439213Sgibbs 50539213Sgibbs if ((trapstr = trap[i]) == NULL) 50639213Sgibbs return; 50739213Sgibbs if (i == 0) 50839213Sgibbs trap[i] = 0; 50959249Sphk RUN(aword, trapstr, nlchar); 51039213Sgibbs} 51139213Sgibbs 51239213Sgibbs/* -------- var.c -------- */ 51339213Sgibbs/* #include "sh.h" */ 51439213Sgibbs 51539213Sgibbs/* 51639213Sgibbs * Find the given name in the dictionary 51739213Sgibbs * and return its value. If the name was 51859249Sphk * not previously there, enter it now and 51939213Sgibbs * return a null value. 52039213Sgibbs */ 52139213Sgibbsstruct var * 52239213Sgibbslookup(n) 52339213Sgibbsregister char *n; 52439213Sgibbs{ 52539213Sgibbs register struct var *vp; 52639213Sgibbs register char *cp; 52739213Sgibbs register int c; 52839213Sgibbs static struct var dummy; 52939213Sgibbs 53039213Sgibbs if (digit(*n)) { 53139213Sgibbs dummy.name = n; 53239213Sgibbs for (c = 0; digit(*n) && c < 1000; n++) 53339213Sgibbs c = c*10 + *n-'0'; 53459249Sphk dummy.status = RONLY; 53539213Sgibbs dummy.value = c <= dolc? dolv[c]: null; 53639213Sgibbs return(&dummy); 53739213Sgibbs } 53839213Sgibbs for (vp = vlist; vp; vp = vp->next) 53939213Sgibbs if (eqname(vp->name, n)) 54039213Sgibbs return(vp); 54139213Sgibbs cp = findeq(n); 54259249Sphk vp = (struct var *)space(sizeof(*vp)); 54339213Sgibbs if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) { 54459249Sphk dummy.name = dummy.value = ""; 54559249Sphk return(&dummy); 54639213Sgibbs } 54750073Sken for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++) 54839213Sgibbs ; 54939213Sgibbs if (*cp == 0) 55039213Sgibbs *cp = '='; 55139213Sgibbs *++cp = 0; 55239213Sgibbs setarea((char *)vp, 0); 55339213Sgibbs setarea((char *)vp->name, 0); 55439213Sgibbs vp->value = null; 55539213Sgibbs vp->next = vlist; 55639213Sgibbs vp->status = GETCELL; 55739213Sgibbs vlist = vp; 55839213Sgibbs return(vp); 55939213Sgibbs} 56039213Sgibbs 56159249Sphk/* 56239213Sgibbs * give variable at `vp' the value `val'. 56339213Sgibbs */ 56439213Sgibbsvoid 56539213Sgibbssetval(vp, val) 56639213Sgibbsstruct var *vp; 56739213Sgibbschar *val; 56839213Sgibbs{ 56939213Sgibbs nameval(vp, val, (char *)NULL); 57039213Sgibbs} 57139213Sgibbs 57239213Sgibbs/* 57339213Sgibbs * if name is not NULL, it must be 57439213Sgibbs * a prefix of the space `val', 57539213Sgibbs * and end with `='. 57639213Sgibbs * this is all so that exporting 57739213Sgibbs * values is reasonably painless. 57839213Sgibbs */ 57939213Sgibbsvoid 58039213Sgibbsnameval(vp, val, name) 58139213Sgibbsregister struct var *vp; 58239213Sgibbschar *val, *name; 58339213Sgibbs{ 58439213Sgibbs register char *cp, *xp; 58559249Sphk char *nv; 58639213Sgibbs int fl; 58739213Sgibbs 58859249Sphk if (vp->status & RONLY) { 58939213Sgibbs for (xp = vp->name; *xp && *xp != '=';) 59039213Sgibbs putc(*xp++); 59139213Sgibbs err(" is read-only"); 59239213Sgibbs return; 59339213Sgibbs } 59439213Sgibbs fl = 0; 59539213Sgibbs if (name == NULL) { 59639213Sgibbs xp = space(strlen(vp->name)+strlen(val)+2); 59739213Sgibbs if (xp == 0) 59839213Sgibbs return; 59946747Sken /* make string: name=value */ 60046747Sken setarea((char *)xp, 0); 60139213Sgibbs name = xp; 60239213Sgibbs for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++) 60339213Sgibbs ; 60439213Sgibbs if (*xp++ == 0) 60539213Sgibbs xp[-1] = '='; 60639213Sgibbs nv = xp; 60739213Sgibbs for (cp = val; (*xp++ = *cp++) != '\0';) 60839213Sgibbs ; 60959249Sphk val = nv; 61039213Sgibbs fl = GETCELL; 61139213Sgibbs } 61239213Sgibbs if (vp->status & GETCELL) 61339213Sgibbs xfree(vp->name); /* form new string `name=value' */ 61439213Sgibbs vp->name = name; 61539213Sgibbs vp->value = val; 61639213Sgibbs vp->status |= fl; 61739213Sgibbs} 61839213Sgibbs 61939213Sgibbsvoid 62039213Sgibbsexport(vp) 62139213Sgibbsstruct var *vp; 62239213Sgibbs{ 62339213Sgibbs vp->status |= EXPORT; 62439213Sgibbs} 62539213Sgibbs 62639213Sgibbsvoid 62739213Sgibbsronly(vp) 62859249Sphkstruct var *vp; 62939213Sgibbs{ 63059249Sphk if (letter(vp->name[0])) /* not an internal symbol ($# etc) */ 63159249Sphk vp->status |= RONLY; 63259249Sphk} 63359249Sphk 63439213Sgibbsint 63539213Sgibbsisassign(s) 63639213Sgibbsregister char *s; 63759249Sphk{ 63859249Sphk if (!letter((int)*s)) 63959249Sphk return(0); 64039213Sgibbs for (; *s != '='; s++) 64159249Sphk if (*s == 0 || !letnum(*s)) 64259249Sphk return(0); 64359249Sphk return(1); 64439213Sgibbs} 64559249Sphk 64639213Sgibbsint 64739213Sgibbsassign(s, cf) 64839213Sgibbsregister char *s; 64939213Sgibbsint cf; 65039213Sgibbs{ 65139213Sgibbs register char *cp; 65239213Sgibbs struct var *vp; 65339213Sgibbs 65439213Sgibbs if (!letter(*s)) 65559249Sphk return(0); 65659249Sphk for (cp = s; *cp != '='; cp++) 65759249Sphk if (*cp == 0 || !letnum(*cp)) 65839213Sgibbs return(0); 65939213Sgibbs vp = lookup(s); 66039213Sgibbs nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); 66139213Sgibbs if (cf != COPYV) 66239213Sgibbs vp->status &= ~GETCELL; 66339213Sgibbs return(1); 66439213Sgibbs} 66539213Sgibbs 66639213Sgibbsint 66739213Sgibbscheckname(cp) 66859249Sphkregister char *cp; 66939213Sgibbs{ 67039213Sgibbs if (!letter(*cp++)) 67139213Sgibbs return(0); 67239213Sgibbs while (*cp) 67339213Sgibbs if (!letnum(*cp++)) 67439213Sgibbs return(0); 67539213Sgibbs return(1); 67639213Sgibbs} 67739213Sgibbs 67839213Sgibbsvoid 67939213Sgibbsputvlist(f, out) 68039213Sgibbsregister int f, out; 68139213Sgibbs{ 68239213Sgibbs register struct var *vp; 68339213Sgibbs 68439213Sgibbs for (vp = vlist; vp; vp = vp->next) 68539213Sgibbs if (vp->status & f && letter(*vp->name)) { 68639213Sgibbs if (vp->status & EXPORT) 68739213Sgibbs write(out, "export ", 7); 68839213Sgibbs if (vp->status & RONLY) 68939213Sgibbs write(out, "readonly ", 9); 69039213Sgibbs write(out, vp->name, (int)(findeq(vp->name) - vp->name)); 69139213Sgibbs write(out, "\n", 1); 69239213Sgibbs } 69350073Sken} 69450073Sken 69550073Skenint 69650073Skeneqname(n1, n2) 69750073Skenregister char *n1, *n2; 69850073Sken{ 69950073Sken for (; *n1 != '=' && *n1 != 0; n1++) 70050073Sken if (*n2++ != *n1) 70150073Sken return(0); 70250073Sken return(*n2 == 0 || *n2 == '='); 70350073Sken} 70450073Sken 70550073Skenstatic char * 70650073Skenfindeq(cp) 70750073Skenregister char *cp; 70850073Sken{ 70950073Sken while (*cp != '\0' && *cp != '=') 71050073Sken cp++; 71150073Sken return(cp); 71250073Sken} 71350073Sken 71450073Sken/* -------- gmatch.c -------- */ 71550073Sken/* 71650073Sken * int gmatch(string, pattern) 71750073Sken * char *string, *pattern; 71850073Sken * 71950073Sken * Match a pattern as in sh(1). 72050073Sken */ 72150073Sken 72250073Sken#define CMASK 0377 72350073Sken#define QUOTE 0200 72450073Sken#define QMASK (CMASK&~QUOTE) 72550073Sken#define NOT '!' /* might use ^ */ 72650073Sken 72750073Skenint 72850073Skengmatch(s, p) 72950073Skenregister char *s, *p; 73050073Sken{ 73150073Sken register int sc, pc; 73250073Sken 73350073Sken if (s == NULL || p == NULL) 73450073Sken return(0); 73550073Sken while ((pc = *p++ & CMASK) != '\0') { 73650073Sken sc = *s++ & QMASK; 73750073Sken switch (pc) { 73850073Sken case '[': 73950073Sken if ((p = cclass(p, sc)) == NULL) 74050073Sken return(0); 74150073Sken break; 74250073Sken 74350073Sken case '?': 74450073Sken if (sc == 0) 74539213Sgibbs return(0); 74639213Sgibbs break; 74739213Sgibbs 74839213Sgibbs case '*': 74939213Sgibbs s--; 75039213Sgibbs do { 75139213Sgibbs if (*p == '\0' || gmatch(s, p)) 75239213Sgibbs return(1); 75339213Sgibbs } while (*s++ != '\0'); 75439213Sgibbs return(0); 75539213Sgibbs 75639213Sgibbs default: 75739213Sgibbs if (sc != (pc&~QUOTE)) 75839213Sgibbs return(0); 75939213Sgibbs } 76039213Sgibbs } 76139213Sgibbs return(*s == 0); 76239213Sgibbs} 76339213Sgibbs 76439213Sgibbsstatic char * 76539213Sgibbscclass(p, sub) 76639213Sgibbsregister char *p; 76739213Sgibbsregister int sub; 76839213Sgibbs{ 76939213Sgibbs register int c, d, not, found; 77039213Sgibbs 771 if ((not = *p == NOT) != 0) 772 p++; 773 found = not; 774 do { 775 if (*p == '\0') 776 return((char *)NULL); 777 c = *p & CMASK; 778 if (p[1] == '-' && p[2] != ']') { 779 d = p[2] & CMASK; 780 p++; 781 } else 782 d = c; 783 if (c == sub || (c <= sub && sub <= d)) 784 found = !not; 785 } while (*++p != ']'); 786 return(found? p+1: (char *)NULL); 787} 788 789/* -------- area.c -------- */ 790#define REGSIZE sizeof(struct region) 791#define GROWBY 256 792#undef SHRINKBY 64 793#define FREE 32767 794#define BUSY 0 795#define ALIGN (sizeof(int)-1) 796 797/* #include "area.h" */ 798 799struct region { 800 struct region *next; 801 int area; 802}; 803 804/* 805 * All memory between (char *)areabot and (char *)(areatop+1) is 806 * exclusively administered by the area management routines. 807 * It is assumed that sbrk() and brk() manipulate the high end. 808 */ 809static struct region *areabot; /* bottom of area */ 810static struct region *areatop; /* top of area */ 811static struct region *areanxt; /* starting point of scan */ 812 813void 814initarea() 815{ 816 while ((int)sbrk(0) & ALIGN) 817 sbrk(1); 818 areabot = (struct region *)sbrk(REGSIZE); 819 areabot->next = areabot; 820 areabot->area = BUSY; 821 areatop = areabot; 822 areanxt = areabot; 823} 824 825char * 826getcell(nbytes) 827unsigned nbytes; 828{ 829 register int nregio; 830 register struct region *p, *q; 831 register i; 832 833 if (nbytes == 0) 834 abort(); /* silly and defeats the algorithm */ 835 /* 836 * round upwards and add administration area 837 */ 838 nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1; 839 for (p = areanxt;;) { 840 if (p->area > areanum) { 841 /* 842 * merge free cells 843 */ 844 while ((q = p->next)->area > areanum && q != areanxt) 845 p->next = q->next; 846 /* 847 * exit loop if cell big enough 848 */ 849 if (q >= p + nregio) 850 goto found; 851 } 852 p = p->next; 853 if (p == areanxt) 854 break; 855 } 856 i = nregio >= GROWBY ? nregio : GROWBY; 857 p = (struct region *)sbrk(i * REGSIZE); 858 if (p == (struct region *)-1) 859 return((char *)NULL); 860 p--; 861 if (p != areatop) 862 abort(); /* allocated areas are contiguous */ 863 q = p + i; 864 p->next = q; 865 p->area = FREE; 866 q->next = areabot; 867 q->area = BUSY; 868 areatop = q; 869found: 870 /* 871 * we found a FREE area big enough, pointed to by 'p', and up to 'q' 872 */ 873 areanxt = p + nregio; 874 if (areanxt < q) { 875 /* 876 * split into requested area and rest 877 */ 878 if (areanxt+1 > q) 879 abort(); /* insufficient space left for admin */ 880 areanxt->next = q; 881 areanxt->area = FREE; 882 p->next = areanxt; 883 } 884 p->area = areanum; 885 return((char *)(p+1)); 886} 887 888void 889freecell(cp) 890char *cp; 891{ 892 register struct region *p; 893 894 if ((p = (struct region *)cp) != NULL) { 895 p--; 896 if (p < areanxt) 897 areanxt = p; 898 p->area = FREE; 899 } 900} 901 902void 903freearea(a) 904register int a; 905{ 906 register struct region *p, *top; 907 908 top = areatop; 909 for (p = areabot; p != top; p = p->next) 910 if (p->area >= a) 911 p->area = FREE; 912} 913 914void 915setarea(cp,a) 916char *cp; 917int a; 918{ 919 register struct region *p; 920 921 if ((p = (struct region *)cp) != NULL) 922 (p-1)->area = a; 923} 924 925int 926getarea(cp) 927char *cp; 928{ 929 return ((struct region*)cp-1)->area; 930} 931 932void 933garbage() 934{ 935 register struct region *p, *q, *top; 936 937 top = areatop; 938 for (p = areabot; p != top; p = p->next) { 939 if (p->area > areanum) { 940 while ((q = p->next)->area > areanum) 941 p->next = q->next; 942 areanxt = p; 943 } 944 } 945#ifdef SHRINKBY 946 if (areatop >= q + SHRINKBY && q->area > areanum) { 947 brk((char *)(q+1)); 948 q->next = areabot; 949 q->area = BUSY; 950 areatop = q; 951 } 952#endif 953} 954