1221828Sgrehan#define Extern extern 2221828Sgrehan#include <sys/types.h> 3221828Sgrehan#include <signal.h> 4221828Sgrehan#define _NSIG NSIG 5221828Sgrehan#include <errno.h> 6221828Sgrehan#include <setjmp.h> 7221828Sgrehan#include "sh.h" 8221828Sgrehan/* -------- sh.c -------- */ 9221828Sgrehan/* 10221828Sgrehan * shell 11221828Sgrehan */ 12221828Sgrehan 13221828Sgrehan/* #include "sh.h" */ 14221828Sgrehan 15221828Sgrehanint intr; 16221828Sgrehanint inparse; 17221828Sgrehanchar flags['z'-'a'+1]; 18221828Sgrehanchar *flag = flags-'a'; 19221828Sgrehanchar *elinep = line+sizeof(line)-5; 20221828Sgrehanchar *null = ""; 21221828Sgrehanint heedint =1; 22221828Sgrehanstruct env e ={line, iostack, iostack-1, 23221828Sgrehan (xint *)NULL, FDBASE, (struct env *)NULL}; 24221828Sgrehan 25221828Sgrehanextern char **environ; /* environment pointer */ 26221828Sgrehan 27221828Sgrehan/* 28221828Sgrehan * default shell, search rules 29221828Sgrehan */ 30221828Sgrehanchar shellname[] = "/bin/sh"; 31221828Sgrehanchar search[] = ":/bin:/usr/bin"; 32221828Sgrehan 33221828Sgrehan_PROTOTYPE(void (*qflag), (int)) = SIG_IGN; 34221828Sgrehan 35221828Sgrehan_PROTOTYPE(int main, (int argc, char **argv )); 36221828Sgrehan_PROTOTYPE(int newfile, (char *s )); 37221828Sgrehan_PROTOTYPE(static char *findeq, (char *cp )); 38221828Sgrehan_PROTOTYPE(static char *cclass, (char *p, int sub )); 39221828Sgrehan_PROTOTYPE(void initarea, (void)); 40221828Sgrehan 41221828Sgrehanint main(argc, argv) 42221828Sgrehanint argc; 43221828Sgrehanregister char **argv; 44221828Sgrehan{ 45221828Sgrehan register int f; 46221828Sgrehan register char *s; 47221828Sgrehan int cflag; 48221828Sgrehan char *name, **ap; 49221828Sgrehan int (*iof)(); 50221828Sgrehan 51221828Sgrehan initarea(); 52221828Sgrehan if ((ap = environ) != NULL) { 53221828Sgrehan while (*ap) 54221828Sgrehan assign(*ap++, !COPYV); 55221828Sgrehan for (ap = environ; *ap;) 56221828Sgrehan export(lookup(*ap++)); 57221828Sgrehan } 58221828Sgrehan closeall(); 59221828Sgrehan areanum = 1; 60221828Sgrehan 61221828Sgrehan shell = lookup("SHELL"); 62221828Sgrehan if (shell->value == null) 63221828Sgrehan setval(shell, shellname); 64221828Sgrehan export(shell); 65221828Sgrehan 66221828Sgrehan homedir = lookup("HOME"); 67221828Sgrehan if (homedir->value == null) 68221828Sgrehan setval(homedir, "/"); 69221828Sgrehan export(homedir); 70221828Sgrehan 71221828Sgrehan setval(lookup("$"), itoa(getpid(), 5)); 72221828Sgrehan 73221828Sgrehan path = lookup("PATH"); 74221828Sgrehan if (path->value == null) 75221828Sgrehan setval(path, search); 76221828Sgrehan export(path); 77221828Sgrehan 78221828Sgrehan ifs = lookup("IFS"); 79221828Sgrehan if (ifs->value == null) 80221828Sgrehan setval(ifs, " \t\n"); 81221828Sgrehan 82221828Sgrehan prompt = lookup("PS1"); 83221828Sgrehan if (prompt->value == null) 84221828Sgrehan#ifndef UNIXSHELL 85221828Sgrehan setval(prompt, "$ "); 86221828Sgrehan#else 87221828Sgrehan setval(prompt, "% "); 88221828Sgrehan#endif 89221828Sgrehan 90221828Sgrehan if (geteuid() == 0) { 91221828Sgrehan setval(prompt, "# "); 92221828Sgrehan prompt->status &= ~EXPORT; 93221828Sgrehan } 94221828Sgrehan cprompt = lookup("PS2"); 95221828Sgrehan if (cprompt->value == null) 96221828Sgrehan setval(cprompt, "> "); 97221828Sgrehan 98221828Sgrehan iof = filechar; 99221828Sgrehan cflag = 0; 100221828Sgrehan name = *argv++; 101221828Sgrehan if (--argc >= 1) { 102221828Sgrehan if(argv[0][0] == '-' && argv[0][1] != '\0') { 103221828Sgrehan for (s = argv[0]+1; *s; s++) 104221828Sgrehan switch (*s) { 105221828Sgrehan case 'c': 106221828Sgrehan prompt->status &= ~EXPORT; 107221828Sgrehan cprompt->status &= ~EXPORT; 108221828Sgrehan setval(prompt, ""); 109221828Sgrehan setval(cprompt, ""); 110221828Sgrehan cflag = 1; 111221828Sgrehan if (--argc > 0) 112221828Sgrehan PUSHIO(aword, *++argv, iof = nlchar); 113221828Sgrehan break; 114221828Sgrehan 115221828Sgrehan case 'q': 116221828Sgrehan qflag = SIG_DFL; 117221828Sgrehan break; 118221828Sgrehan 119221828Sgrehan case 's': 120221828Sgrehan /* standard input */ 121221828Sgrehan break; 122221828Sgrehan 123221828Sgrehan case 't': 124221828Sgrehan prompt->status &= ~EXPORT; 125221828Sgrehan setval(prompt, ""); 126221828Sgrehan iof = linechar; 127221828Sgrehan break; 128221828Sgrehan 129221828Sgrehan case 'i': 130221828Sgrehan talking++; 131221828Sgrehan default: 132221828Sgrehan if (*s>='a' && *s<='z') 133221828Sgrehan flag[*s]++; 134221828Sgrehan } 135221828Sgrehan } else { 136221828Sgrehan argv--; 137221828Sgrehan argc++; 138221828Sgrehan } 139221828Sgrehan if (iof == filechar && --argc > 0) { 140221828Sgrehan setval(prompt, ""); 141221828Sgrehan setval(cprompt, ""); 142221828Sgrehan prompt->status &= ~EXPORT; 143221828Sgrehan cprompt->status &= ~EXPORT; 144221828Sgrehan if (newfile(name = *++argv)) 145221828Sgrehan exit(1); 146221828Sgrehan } 147221828Sgrehan } 148221828Sgrehan setdash(); 149221828Sgrehan if (e.iop < iostack) { 150221828Sgrehan PUSHIO(afile, 0, iof); 151221828Sgrehan if (isatty(0) && isatty(1) && !cflag) 152221828Sgrehan talking++; 153221828Sgrehan } 154221828Sgrehan signal(SIGQUIT, qflag); 155221828Sgrehan if (name && name[0] == '-') { 156221828Sgrehan talking++; 157221828Sgrehan if ((f = open(".profile", 0)) >= 0) 158221828Sgrehan next(remap(f)); 159221828Sgrehan if ((f = open("/etc/profile", 0)) >= 0) 160221828Sgrehan next(remap(f)); 161221828Sgrehan } 162221828Sgrehan if (talking) 163221828Sgrehan signal(SIGTERM, sig); 164221828Sgrehan if (signal(SIGINT, SIG_IGN) != SIG_IGN) 165221828Sgrehan signal(SIGINT, onintr); 166221828Sgrehan dolv = argv; 167221828Sgrehan dolc = argc; 168221828Sgrehan dolv[0] = name; 169221828Sgrehan if (dolc > 1) 170221828Sgrehan for (ap = ++argv; --argc > 0;) 171221828Sgrehan if (assign(*ap = *argv++, !COPYV)) 172221828Sgrehan dolc--; /* keyword */ 173221828Sgrehan else 174221828Sgrehan ap++; 175221828Sgrehan setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); 176221828Sgrehan 177221828Sgrehan for (;;) { 178221828Sgrehan if (talking && e.iop <= iostack) 179221828Sgrehan prs(prompt->value); 180221828Sgrehan onecommand(); 181221828Sgrehan } 182221828Sgrehan} 183221828Sgrehan 184221828Sgrehanvoid 185221828Sgrehansetdash() 186221828Sgrehan{ 187221828Sgrehan register char *cp, c; 188221828Sgrehan char m['z'-'a'+1]; 189221828Sgrehan 190221828Sgrehan cp = m; 191221828Sgrehan for (c='a'; c<='z'; c++) 192221828Sgrehan if (flag[c]) 193221828Sgrehan *cp++ = c; 194221828Sgrehan *cp = 0; 195221828Sgrehan setval(lookup("-"), m); 196221828Sgrehan} 197221828Sgrehan 198221828Sgrehanint 199221828Sgrehannewfile(s) 200221828Sgrehanregister char *s; 201221828Sgrehan{ 202221828Sgrehan register f; 203221828Sgrehan 204221828Sgrehan if (strcmp(s, "-") != 0) { 205221828Sgrehan f = open(s, 0); 206221828Sgrehan if (f < 0) { 207221828Sgrehan prs(s); 208221828Sgrehan err(": cannot open"); 209221828Sgrehan return(1); 210221828Sgrehan } 211221828Sgrehan } else 212221828Sgrehan f = 0; 213221828Sgrehan next(remap(f)); 214221828Sgrehan return(0); 215221828Sgrehan} 216221828Sgrehan 217221828Sgrehanvoid 218221828Sgrehanonecommand() 219221828Sgrehan{ 220221828Sgrehan register i; 221221828Sgrehan jmp_buf m1; 222221828Sgrehan 223221828Sgrehan while (e.oenv) 224221828Sgrehan quitenv(); 225221828Sgrehan areanum = 1; 226221828Sgrehan freehere(areanum); 227221828Sgrehan freearea(areanum); 228221828Sgrehan garbage(); 229221828Sgrehan wdlist = 0; 230221828Sgrehan iolist = 0; 231221828Sgrehan e.errpt = 0; 232221828Sgrehan e.linep = line; 233221828Sgrehan yynerrs = 0; 234221828Sgrehan multiline = 0; 235221828Sgrehan inparse = 1; 236221828Sgrehan intr = 0; 237221828Sgrehan execflg = 0; 238221828Sgrehan setjmp(failpt = m1); /* Bruce Evans' fix */ 239221828Sgrehan if (setjmp(failpt = m1) || yyparse() || intr) { 240221828Sgrehan while (e.oenv) 241221828Sgrehan quitenv(); 242221828Sgrehan scraphere(); 243221828Sgrehan if (!talking && intr) 244221828Sgrehan leave(); 245221828Sgrehan inparse = 0; 246221828Sgrehan intr = 0; 247221828Sgrehan return; 248221828Sgrehan } 249221828Sgrehan inparse = 0; 250221828Sgrehan brklist = 0; 251221828Sgrehan intr = 0; 252221828Sgrehan execflg = 0; 253221828Sgrehan if (!flag['n']) 254221828Sgrehan execute(outtree, NOPIPE, NOPIPE, 0); 255221828Sgrehan if (!talking && intr) { 256221828Sgrehan execflg = 0; 257221828Sgrehan leave(); 258221828Sgrehan } 259221828Sgrehan if ((i = trapset) != 0) { 260221828Sgrehan trapset = 0; 261221828Sgrehan runtrap(i); 262221828Sgrehan } 263221828Sgrehan} 264221828Sgrehan 265221828Sgrehanvoid 266221828Sgrehanfail() 267221828Sgrehan{ 268221828Sgrehan longjmp(failpt, 1); 269221828Sgrehan /* NOTREACHED */ 270221828Sgrehan} 271221828Sgrehan 272221828Sgrehanvoid 273221828Sgrehanleave() 274221828Sgrehan{ 275221828Sgrehan if (execflg) 276221828Sgrehan fail(); 277221828Sgrehan scraphere(); 278221828Sgrehan freehere(1); 279221828Sgrehan runtrap(0); 280221828Sgrehan exit(exstat); 281221828Sgrehan /* NOTREACHED */ 282221828Sgrehan} 283221828Sgrehan 284221828Sgrehanvoid 285221828Sgrehanwarn(s) 286221828Sgrehanregister char *s; 287221828Sgrehan{ 288221828Sgrehan if(*s) { 289221828Sgrehan prs(s); 290221828Sgrehan exstat = -1; 291221828Sgrehan } 292221828Sgrehan prs("\n"); 293221828Sgrehan if (flag['e']) 294221828Sgrehan leave(); 295221828Sgrehan} 296221828Sgrehan 297221828Sgrehanvoid 298221828Sgrehanerr(s) 299221828Sgrehanchar *s; 300221828Sgrehan{ 301221828Sgrehan warn(s); 302221828Sgrehan if (flag['n']) 303221828Sgrehan return; 304221828Sgrehan if (!talking) 305221828Sgrehan leave(); 306221828Sgrehan if (e.errpt) 307221828Sgrehan longjmp(e.errpt, 1); 308221828Sgrehan closeall(); 309221828Sgrehan e.iop = e.iobase = iostack; 310221828Sgrehan} 311221828Sgrehan 312221828Sgrehanint 313221828Sgrehannewenv(f) 314221828Sgrehanint f; 315221828Sgrehan{ 316221828Sgrehan register struct env *ep; 317239026Sneel 318239026Sneel if (f) { 319239026Sneel quitenv(); 320239026Sneel return(1); 321239026Sneel } 322239026Sneel ep = (struct env *) space(sizeof(*ep)); 323239026Sneel if (ep == NULL) { 324239026Sneel while (e.oenv) 325239026Sneel quitenv(); 326239026Sneel fail(); 327221828Sgrehan } 328221828Sgrehan *ep = e; 329221828Sgrehan e.oenv = ep; 330221828Sgrehan e.errpt = errpt; 331221828Sgrehan return(0); 332221828Sgrehan} 333221828Sgrehan 334221828Sgrehanvoid 335221828Sgrehanquitenv() 336221828Sgrehan{ 337221828Sgrehan register struct env *ep; 338221828Sgrehan register fd; 339221828Sgrehan 340221828Sgrehan if ((ep = e.oenv) != NULL) { 341221828Sgrehan fd = e.iofd; 342221828Sgrehan e = *ep; 343221828Sgrehan /* should close `'d files */ 344221828Sgrehan DELETE(ep); 345221828Sgrehan while (--fd >= e.iofd) 346221828Sgrehan close(fd); 347221828Sgrehan } 348221828Sgrehan} 349221828Sgrehan 350221828Sgrehan/* 351221828Sgrehan * Is any character from s1 in s2? 352221828Sgrehan */ 353221828Sgrehanint 354221828Sgrehananys(s1, s2) 355221828Sgrehanregister char *s1, *s2; 356221828Sgrehan{ 357221828Sgrehan while (*s1) 358221828Sgrehan if (any(*s1++, s2)) 359221828Sgrehan return(1); 360221828Sgrehan return(0); 361221828Sgrehan} 362221828Sgrehan 363221828Sgrehan/* 364221828Sgrehan * Is character c in s? 365221828Sgrehan */ 366221828Sgrehanint 367221828Sgrehanany(c, s) 368221828Sgrehanregister int c; 369221828Sgrehanregister char *s; 370221828Sgrehan{ 371221828Sgrehan while (*s) 372221828Sgrehan if (*s++ == c) 373221828Sgrehan return(1); 374221828Sgrehan return(0); 375221828Sgrehan} 376221828Sgrehan 377221828Sgrehanchar * 378221828Sgrehanputn(n) 379221828Sgrehanregister int n; 380221828Sgrehan{ 381221828Sgrehan return(itoa(n, -1)); 382221828Sgrehan} 383221828Sgrehan 384221828Sgrehanchar * 385221828Sgrehanitoa(u, n) 386221828Sgrehanregister unsigned u; 387221828Sgrehanint n; 388221828Sgrehan{ 389221828Sgrehan register char *cp; 390221828Sgrehan static char s[20]; 391221828Sgrehan int m; 392221828Sgrehan 393221828Sgrehan m = 0; 394221828Sgrehan if (n < 0 && (int) u < 0) { 395221828Sgrehan m++; 396221828Sgrehan u = -u; 397221828Sgrehan } 398221828Sgrehan cp = s+sizeof(s); 399221828Sgrehan *--cp = 0; 400221828Sgrehan do { 401221828Sgrehan *--cp = u%10 + '0'; 402221828Sgrehan u /= 10; 403221828Sgrehan } while (--n > 0 || u); 404221828Sgrehan if (m) 405221828Sgrehan *--cp = '-'; 406221828Sgrehan return(cp); 407221828Sgrehan} 408221828Sgrehan 409221828Sgrehanvoid 410221828Sgrehannext(f) 411221828Sgrehanint f; 412221828Sgrehan{ 413221828Sgrehan PUSHIO(afile, f, filechar); 414221828Sgrehan} 415221828Sgrehan 416221828Sgrehanvoid 417221828Sgrehanonintr(s) 418221828Sgrehanint s; /* ANSI C requires a parameter */ 419221828Sgrehan{ 420221828Sgrehan signal(SIGINT, onintr); 421221828Sgrehan intr = 1; 422221828Sgrehan if (talking) { 423221828Sgrehan if (inparse) { 424221828Sgrehan prs("\n"); 425221828Sgrehan fail(); 426221828Sgrehan } 427221828Sgrehan } 428221828Sgrehan else if (heedint) { 429221828Sgrehan execflg = 0; 430221828Sgrehan leave(); 431221828Sgrehan } 432221828Sgrehan} 433221828Sgrehan 434221828Sgrehanint 435221828Sgrehanletter(c) 436221828Sgrehanregister c; 437221828Sgrehan{ 438221828Sgrehan return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'); 439221828Sgrehan} 440221828Sgrehan 441221828Sgrehanint 442221828Sgrehandigit(c) 443221828Sgrehanregister c; 444221828Sgrehan{ 445221828Sgrehan return(c >= '0' && c <= '9'); 446221828Sgrehan} 447221828Sgrehan 448221828Sgrehanint 449221828Sgrehanletnum(c) 450221828Sgrehanregister c; 451221828Sgrehan{ 452221828Sgrehan return(letter(c) || digit(c)); 453221828Sgrehan} 454221828Sgrehan 455221828Sgrehanchar * 456221828Sgrehanspace(n) 457221828Sgrehanint n; 458221828Sgrehan{ 459221828Sgrehan register char *cp; 460221828Sgrehan 461221828Sgrehan if ((cp = getcell(n)) == 0) 462221828Sgrehan err("out of string space"); 463234761Sgrehan return(cp); 464234761Sgrehan} 465234761Sgrehan 466234761Sgrehanchar * 467234761Sgrehanstrsave(s, a) 468234761Sgrehanregister char *s; 469234761Sgrehanint a; 470234761Sgrehan{ 471234761Sgrehan register char *cp, *xp; 472234761Sgrehan 473234761Sgrehan if ((cp = space(strlen(s)+1)) != NULL) { 474234761Sgrehan setarea((char *)cp, a); 475234761Sgrehan for (xp = cp; (*xp++ = *s++) != '\0';) 476234761Sgrehan ; 477234761Sgrehan return(cp); 478234761Sgrehan } 479234761Sgrehan return(""); 480234761Sgrehan} 481234761Sgrehan 482221828Sgrehanvoid 483221828Sgrehanxfree(s) 484221828Sgrehanregister char *s; 485221828Sgrehan{ 486221828Sgrehan DELETE(s); 487221828Sgrehan} 488221828Sgrehan 489221828Sgrehan/* 490221828Sgrehan * trap handling 491221828Sgrehan */ 492221828Sgrehanvoid 493221828Sgrehansig(i) 494221828Sgrehanregister int i; 495221828Sgrehan{ 496221828Sgrehan trapset = i; 497221828Sgrehan signal(i, sig); 498221828Sgrehan} 499221828Sgrehan 500221828Sgrehanvoid runtrap(i) 501221828Sgrehanint i; 502221828Sgrehan{ 503221828Sgrehan char *trapstr; 504221828Sgrehan 505221828Sgrehan if ((trapstr = trap[i]) == NULL) 506221828Sgrehan return; 507221828Sgrehan if (i == 0) 508221828Sgrehan trap[i] = 0; 509221828Sgrehan RUN(aword, trapstr, nlchar); 510221828Sgrehan} 511221828Sgrehan 512221828Sgrehan/* -------- var.c -------- */ 513221828Sgrehan/* #include "sh.h" */ 514221828Sgrehan 515221828Sgrehan/* 516221828Sgrehan * Find the given name in the dictionary 517221828Sgrehan * and return its value. If the name was 518221828Sgrehan * not previously there, enter it now and 519221828Sgrehan * return a null value. 520221828Sgrehan */ 521221828Sgrehanstruct var * 522221828Sgrehanlookup(n) 523221828Sgrehanregister char *n; 524221828Sgrehan{ 525221828Sgrehan register struct var *vp; 526221828Sgrehan register char *cp; 527221828Sgrehan register int c; 528221828Sgrehan static struct var dummy; 529221828Sgrehan 530221828Sgrehan if (digit(*n)) { 531221828Sgrehan dummy.name = n; 532221828Sgrehan for (c = 0; digit(*n) && c < 1000; n++) 533221828Sgrehan c = c*10 + *n-'0'; 534221828Sgrehan dummy.status = RONLY; 535221828Sgrehan dummy.value = c <= dolc? dolv[c]: null; 536221828Sgrehan return(&dummy); 537221828Sgrehan } 538221828Sgrehan for (vp = vlist; vp; vp = vp->next) 539221828Sgrehan if (eqname(vp->name, n)) 540221828Sgrehan return(vp); 541221828Sgrehan cp = findeq(n); 542221828Sgrehan vp = (struct var *)space(sizeof(*vp)); 543221828Sgrehan if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) { 544221828Sgrehan dummy.name = dummy.value = ""; 545239025Sneel return(&dummy); 546221828Sgrehan } 547221828Sgrehan for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++) 548221828Sgrehan ; 549221828Sgrehan if (*cp == 0) 550221828Sgrehan *cp = '='; 551221828Sgrehan *++cp = 0; 552221828Sgrehan setarea((char *)vp, 0); 553221828Sgrehan setarea((char *)vp->name, 0); 554221828Sgrehan vp->value = null; 555221828Sgrehan vp->next = vlist; 556221828Sgrehan vp->status = GETCELL; 557221828Sgrehan vlist = vp; 558221828Sgrehan return(vp); 559221828Sgrehan} 560221828Sgrehan 561221828Sgrehan/* 562221828Sgrehan * give variable at `vp' the value `val'. 563221828Sgrehan */ 564221828Sgrehanvoid 565221828Sgrehansetval(vp, val) 566221828Sgrehanstruct var *vp; 567221828Sgrehanchar *val; 568221828Sgrehan{ 569221828Sgrehan nameval(vp, val, (char *)NULL); 570221828Sgrehan} 571221828Sgrehan 572221828Sgrehan/* 573221828Sgrehan * if name is not NULL, it must be 574221828Sgrehan * a prefix of the space `val', 575221828Sgrehan * and end with `='. 576221828Sgrehan * this is all so that exporting 577221828Sgrehan * values is reasonably painless. 578221828Sgrehan */ 579221828Sgrehanvoid 580221828Sgrehannameval(vp, val, name) 581221828Sgrehanregister struct var *vp; 582221828Sgrehanchar *val, *name; 583221828Sgrehan{ 584221828Sgrehan register char *cp, *xp; 585221828Sgrehan char *nv; 586221828Sgrehan int fl; 587221828Sgrehan 588221828Sgrehan if (vp->status & RONLY) { 589221828Sgrehan for (xp = vp->name; *xp && *xp != '=';) 590221828Sgrehan putc(*xp++); 591221828Sgrehan err(" is read-only"); 592221828Sgrehan return; 593221828Sgrehan } 594221828Sgrehan fl = 0; 595221828Sgrehan if (name == NULL) { 596221828Sgrehan xp = space(strlen(vp->name)+strlen(val)+2); 597221828Sgrehan if (xp == 0) 598221828Sgrehan return; 599221828Sgrehan /* make string: name=value */ 600221828Sgrehan setarea((char *)xp, 0); 601221828Sgrehan name = xp; 602221828Sgrehan for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++) 603221828Sgrehan ; 604221828Sgrehan if (*xp++ == 0) 605221828Sgrehan xp[-1] = '='; 606221828Sgrehan nv = xp; 607221828Sgrehan for (cp = val; (*xp++ = *cp++) != '\0';) 608221828Sgrehan ; 609221828Sgrehan val = nv; 610221828Sgrehan fl = GETCELL; 611221828Sgrehan } 612221828Sgrehan if (vp->status & GETCELL) 613221828Sgrehan xfree(vp->name); /* form new string `name=value' */ 614221828Sgrehan vp->name = name; 615221828Sgrehan vp->value = val; 616221828Sgrehan vp->status |= fl; 617221828Sgrehan} 618221828Sgrehan 619221828Sgrehanvoid 620221828Sgrehanexport(vp) 621221828Sgrehanstruct var *vp; 622221828Sgrehan{ 623221828Sgrehan vp->status |= EXPORT; 624221828Sgrehan} 625221828Sgrehan 626221828Sgrehanvoid 627221828Sgrehanronly(vp) 628221828Sgrehanstruct var *vp; 629221828Sgrehan{ 630221828Sgrehan if (letter(vp->name[0])) /* not an internal symbol ($# etc) */ 631221828Sgrehan vp->status |= RONLY; 632221828Sgrehan} 633221828Sgrehan 634221828Sgrehanint 635221828Sgrehanisassign(s) 636221828Sgrehanregister char *s; 637221828Sgrehan{ 638221828Sgrehan if (!letter((int)*s)) 639221828Sgrehan return(0); 640221828Sgrehan for (; *s != '='; s++) 641221828Sgrehan if (*s == 0 || !letnum(*s)) 642221828Sgrehan return(0); 643221828Sgrehan return(1); 644221828Sgrehan} 645221828Sgrehan 646221828Sgrehanint 647221828Sgrehanassign(s, cf) 648221828Sgrehanregister char *s; 649221828Sgrehanint cf; 650221828Sgrehan{ 651221828Sgrehan register char *cp; 652221828Sgrehan struct var *vp; 653221828Sgrehan 654221828Sgrehan if (!letter(*s)) 655221828Sgrehan return(0); 656221828Sgrehan for (cp = s; *cp != '='; cp++) 657221828Sgrehan if (*cp == 0 || !letnum(*cp)) 658221828Sgrehan return(0); 659221828Sgrehan vp = lookup(s); 660221828Sgrehan nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); 661221828Sgrehan if (cf != COPYV) 662221828Sgrehan vp->status &= ~GETCELL; 663221828Sgrehan return(1); 664221828Sgrehan} 665221828Sgrehan 666221828Sgrehanint 667221828Sgrehancheckname(cp) 668221828Sgrehanregister char *cp; 669221828Sgrehan{ 670221828Sgrehan if (!letter(*cp++)) 671 return(0); 672 while (*cp) 673 if (!letnum(*cp++)) 674 return(0); 675 return(1); 676} 677 678void 679putvlist(f, out) 680register int f, out; 681{ 682 register struct var *vp; 683 684 for (vp = vlist; vp; vp = vp->next) 685 if (vp->status & f && letter(*vp->name)) { 686 if (vp->status & EXPORT) 687 write(out, "export ", 7); 688 if (vp->status & RONLY) 689 write(out, "readonly ", 9); 690 write(out, vp->name, (int)(findeq(vp->name) - vp->name)); 691 write(out, "\n", 1); 692 } 693} 694 695int 696eqname(n1, n2) 697register char *n1, *n2; 698{ 699 for (; *n1 != '=' && *n1 != 0; n1++) 700 if (*n2++ != *n1) 701 return(0); 702 return(*n2 == 0 || *n2 == '='); 703} 704 705static char * 706findeq(cp) 707register char *cp; 708{ 709 while (*cp != '\0' && *cp != '=') 710 cp++; 711 return(cp); 712} 713 714/* -------- gmatch.c -------- */ 715/* 716 * int gmatch(string, pattern) 717 * char *string, *pattern; 718 * 719 * Match a pattern as in sh(1). 720 */ 721 722#define CMASK 0377 723#define QUOTE 0200 724#define QMASK (CMASK&~QUOTE) 725#define NOT '!' /* might use ^ */ 726 727int 728gmatch(s, p) 729register char *s, *p; 730{ 731 register int sc, pc; 732 733 if (s == NULL || p == NULL) 734 return(0); 735 while ((pc = *p++ & CMASK) != '\0') { 736 sc = *s++ & QMASK; 737 switch (pc) { 738 case '[': 739 if ((p = cclass(p, sc)) == NULL) 740 return(0); 741 break; 742 743 case '?': 744 if (sc == 0) 745 return(0); 746 break; 747 748 case '*': 749 s--; 750 do { 751 if (*p == '\0' || gmatch(s, p)) 752 return(1); 753 } while (*s++ != '\0'); 754 return(0); 755 756 default: 757 if (sc != (pc&~QUOTE)) 758 return(0); 759 } 760 } 761 return(*s == 0); 762} 763 764static char * 765cclass(p, sub) 766register char *p; 767register int sub; 768{ 769 register int c, d, not, found; 770 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