|
|
1.1 ! root 1: /* ! 2: * startup, main loop, enviroments and error handling ! 3: */ ! 4: ! 5: static char *RCSid = "$Header: /newbits/usr/bin/korn/RCS/main.c,v 1.2 91/08/01 12:41:00 bin Exp Locker: bin $"; ! 6: ! 7: #define TRACE_PRINT printf ! 8: ! 9: #define Extern /* define Externs in sh.h */ ! 10: ! 11: #include <stddef.h> ! 12: #include <stdlib.h> ! 13: #include <stdio.h> ! 14: #include <string.h> ! 15: #include <unistd.h> ! 16: #include <sys/fcntl.h> ! 17: #include <signal.h> ! 18: #include <errno.h> ! 19: #include <setjmp.h> ! 20: #include "sh.h" ! 21: #include "lex.h" ! 22: #include "tree.h" ! 23: #include "table.h" ! 24: ! 25: /* ! 26: * global data ! 27: */ ! 28: ! 29: Area aperm; ! 30: ! 31: static void reclaim ARGS((void)); ! 32: ! 33: /* ! 34: * shell initialization ! 35: */ ! 36: ! 37: static char initifs [] = "IFS= \t\n"; /* must be R/W */ ! 38: ! 39: static Const char initsubs [] = ! 40: "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> }"; ! 41: ! 42: static Const char *initcoms [] = { ! 43: "cd", ".", NULL, /* set up $PWD */ ! 44: "typeset", "-x", "SHELL", "PATH", "HOME", NULL, ! 45: "typeset", "-r", "PWD", "OLDPWD", NULL, ! 46: "typeset", "-i", "SECONDS=0", "OPTIND", NULL, ! 47: "alias", ! 48: "integer=typeset -i", "pwd=print -r \"$PWD\"", ! 49: "history=fc -l", "r=fc -s", ! 50: #if !COHERENT ! 51: "nohup=nohup ", ! 52: #endif ! 53: "login=exec login", "newgrp=exec newgrp", ! 54: "type=whence -v", "functions=typeset -f", ! 55: "echo=print", "true=:", "false=let", "[=\\[", NULL, ! 56: NULL ! 57: }; ! 58: ! 59: main(argc, argv, envp) ! 60: int argc; ! 61: register char **argv; ! 62: char **envp; ! 63: { ! 64: register int i; ! 65: register char *arg; ! 66: int cflag = 0, qflag = 0; ! 67: char *name; ! 68: register Source *s; ! 69: register struct block *l = &globals; ! 70: register char **wp0, **wp; ! 71: extern char ksh_version []; ! 72: ! 73: ainit(&aperm); /* initialize permanent Area */ ! 74: ! 75: /* set up base enviroment */ ! 76: e.type = E_NONE; ! 77: ainit(&e.area); ! 78: e.loc = l; ! 79: e.savefd = NULL; ! 80: e.oenv = NULL; ! 81: ! 82: initctypes(); ! 83: ! 84: /* open file streams for fd's 0,1,2 */ ! 85: fopenshf(0); fopenshf(1); fopenshf(2); ! 86: ! 87: /* set up variable and command dictionaries */ ! 88: newblock(); /* set up global l->vars and l->funs */ ! 89: tinit(&commands, APERM); ! 90: tinit(&builtins, APERM); ! 91: tinit(&lexicals, APERM); ! 92: tinit(&homedirs, APERM); ! 93: ! 94: /* import enviroment */ ! 95: if (envp != NULL) ! 96: for (wp = envp; *wp != NULL; wp++) ! 97: import(*wp); ! 98: ! 99: typeset(initifs, 0, 0); /* for security */ ! 100: typeset(ksh_version, 0, 0); /* RDONLY */ ! 101: ! 102: /* define shell keywords */ ! 103: keywords(); ! 104: ! 105: /* define built-in commands */ ! 106: for (i = 0; shbuiltins[i].name != NULL; i++) ! 107: builtin(shbuiltins[i].name, shbuiltins[i].func); ! 108: for (i = 0; kshbuiltins[i].name != NULL; i++) ! 109: builtin(kshbuiltins[i].name, kshbuiltins[i].func); ! 110: ! 111: /* assign default shell variable values */ ! 112: substitute(initsubs, 0); ! 113: /* execute initialization statements */ ! 114: for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) { ! 115: /* copy because the alias initializers are readonly */ ! 116: for (wp = wp0; *wp != NULL; wp++) ! 117: *wp = strsave(*wp, ATEMP); ! 118: shcomexec(wp0); ! 119: } ! 120: afreeall(ATEMP); ! 121: ! 122: if (geteuid() == 0) ! 123: setstr(global("PS1"), "# "); ! 124: ! 125: s = pushs(SFILE); ! 126: s->u.file = stdin; ! 127: cflag = 0; ! 128: name = *argv++; ! 129: ! 130: /* what a bloody mess */ ! 131: if (--argc >= 1) { ! 132: if (argv[0][0] == '-' && argv[0][1] != '\0') { ! 133: for (arg = argv[0]+1; *arg; arg++) ! 134: switch (*arg) { ! 135: case 'c': ! 136: cflag = 1; ! 137: if (--argc > 0) { ! 138: s->type = SSTRING; ! 139: s->str = *++argv; ! 140: } ! 141: break; ! 142: ! 143: case 'q': ! 144: qflag = 1; ! 145: break; ! 146: ! 147: default: ! 148: if (*arg>='a' && *arg<='z') ! 149: flag[FLAG(*arg)]++; ! 150: } ! 151: } else { ! 152: argv--; ! 153: argc++; ! 154: } ! 155: if (s->type == SFILE && --argc > 0) { ! 156: if ((s->u.file = fopen(*++argv, "r")) == NULL) ! 157: errorf("%s: cannot open\n", *argv); ! 158: s->file = *argv; ! 159: fileno(s->u.file) = savefd(fileno(s->u.file)); ! 160: setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ); ! 161: } ! 162: } ! 163: ! 164: if (s->type == SFILE) { ! 165: if (fileno(s->u.file) == 0) ! 166: flag[FSTDIN] = 1; ! 167: if (isatty(0) && isatty(1) && !cflag) ! 168: flag[FTALKING] = 1; ! 169: if (flag[FTALKING] && flag[FSTDIN]) ! 170: s->type = STTY; ! 171: } ! 172: if (s->type == STTY) { ! 173: TRACE_PRINT("main: about to call fcntl. The next step is .profile\n"); ! 174: ttyfd = fcntl(0, F_DUPFD, FDBASE); ! 175: TRACE_PRINT("main: ttyfd = %d\n"); ! 176: #if !COHERENT ! 177: (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC); ! 178: #endif ! 179: #if EDIT ! 180: x_init(); ! 181: TRACE_PRINT("main: x_init done!\n"); ! 182: #endif ! 183: } ! 184: ! 185: /* initialize job control */ ! 186: j_init(); ! 187: TRACE_PRINT("main: j_int() done!\n"); ! 188: if (!qflag) ! 189: ignoresig(SIGQUIT); ! 190: ! 191: if (name[0] == '-') { ! 192: flag[FTALKING] = 1; ! 193: #if !COHERENT ! 194: (void) include("/etc/profile"); ! 195: #endif ! 196: (void) include(".profile"); ! 197: TRACE_PRINT("main: .profile included!\n"); ! 198: } ! 199: ! 200: /* include $ENV */ ! 201: arg = substitute(strval(global("ENV")), DOTILDE); ! 202: if (*arg != '\0') ! 203: (void) include(arg); ! 204: ! 205: if (flag[FTALKING]) { ! 206: signal(SIGTERM, trapsig); ! 207: ignoresig(SIGINT); ! 208: } else ! 209: flag[FHASHALL] = 1; ! 210: ! 211: #if JOBS /* todo: could go before includes? */ ! 212: if (s->type == STTY) { ! 213: flag[FMONITOR] = 1; ! 214: TRACE_PRINT("main: about to call j_change()\n"); ! 215: j_change(); ! 216: TRACE_PRINT("main: j_change done!\n"); ! 217: } ! 218: #endif ! 219: ! 220: l->argv = argv; ! 221: l->argc = argc; ! 222: l->argv[0] = name; ! 223: TRACE_PRINT("main: resetting opts\n"); ! 224: resetopts(); ! 225: TRACE_PRINT("main: resetting opts done!\n"); ! 226: ! 227: argc = shell(s); ! 228: leave(argc); ! 229: } ! 230: ! 231: int ! 232: include(name) ! 233: register char *name; ! 234: { ! 235: register FILE *f; ! 236: register Source *s; ! 237: ! 238: if (strcmp(name, "-") != 0) { ! 239: f = fopen(name, "r"); ! 240: if (f == NULL) ! 241: return 0; ! 242: /* todo: the savefd doesn't get popped */ ! 243: TRACE_PRINT("include(): About to call savefd\n"); ! 244: fileno(f) = savefd(fileno(f)); /* questionable */ ! 245: setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ); ! 246: } else ! 247: f = stdin; ! 248: s = pushs(SFILE); ! 249: s->u.file = f; ! 250: s->file = name; ! 251: /*return*/ shell(s); ! 252: if (f != stdin) ! 253: fclose(f); ! 254: return 1; ! 255: } ! 256: ! 257: int ! 258: command(comm) ! 259: register char *comm; ! 260: { ! 261: register Source *s; ! 262: ! 263: s = pushs(SSTRING); ! 264: s->str = comm; ! 265: return shell(s); ! 266: } ! 267: ! 268: /* ! 269: * run the commands from the input source, returning status. ! 270: */ ! 271: int ! 272: shell(s) ! 273: Source *s; /* input source */ ! 274: { ! 275: struct op *t; ! 276: Volatile int attempts = 13; ! 277: ! 278: newenv(E_PARSE); ! 279: e.interactive = 1; ! 280: exstat = 0; ! 281: if (setjmp(e.jbuf)) { ! 282: /*shellf("<unwind>");*/ ! 283: if (trap) /* pending SIGINT */ ! 284: shellf("\n"); ! 285: sigtraps[SIGINT].set = 0; ! 286: } ! 287: ! 288: while (1) { ! 289: if (trap){ ! 290: TRACE_PRINT("shell: About to runtraps()\n"); ! 291: runtraps(); ! 292: TRACE_PRINT("shell: runtraps() done!\n"); ! 293: } ! 294: if (flag[FTALKING]){ ! 295: TRACE_PRINT("shell: about to signal (sigint, trapsig)\n"); ! 296: signal(SIGINT, trapsig); ! 297: TRACE_PRINT("shell: trapsig done!\n"); ! 298: } ! 299: if (s->next == NULL){ ! 300: TRACE_PRINT("shell: s->echo is NIL\n"); ! 301: s->echo = flag[FVERBOSE]; ! 302: } ! 303: j_notify(); ! 304: ! 305: if (s->type == STTY) ! 306: prompt = substitute(strval(global("PS1")), 0); ! 307: ! 308: t = compile(s); ! 309: if (t != NULL && t->type == TEOF) ! 310: if (s->type == SEOF && flag[FIGNEOF] && --attempts > 0) { ! 311: s->type = STTY; ! 312: shellf("Use `exit'\n"); ! 313: } else{ ! 314: TRACE_PRINT("shell: t is not NIL. About to break!\n"); ! 315: break; ! 316: } ! 317: flushshf(2); /* flush -v output */ ! 318: ! 319: if (!flag[FNOEXEC] || s->type == STTY){ ! 320: TRACE_PRINT("shell: about to execute()\n"); ! 321: execute(t, 0); ! 322: } ! 323: TRACE_PRINT("shell: about to reclaim()\n"); ! 324: reclaim(); ! 325: } ! 326: Error: ! 327: quitenv(); ! 328: return exstat; ! 329: } ! 330: ! 331: void ! 332: leave(rv) ! 333: int rv; ! 334: { ! 335: if (e.type == E_TCOM && e.oenv != NULL) /* exec'd command */ ! 336: unwind(); ! 337: runtrap(&sigtraps[0]); ! 338: j_exit(); ! 339: exit(rv); ! 340: /* NOTREACHED */ ! 341: } ! 342: ! 343: error() ! 344: { ! 345: if (flag[FERREXIT] || !flag[FTALKING]) ! 346: leave(1); ! 347: unwind(); ! 348: } ! 349: ! 350: /* return to closest error handler or shell(), exit if none found */ ! 351: unwind() ! 352: { ! 353: while (1) ! 354: switch (e.type) { ! 355: case E_NONE: ! 356: leave(1); ! 357: /* NOTREACHED */ ! 358: case E_PARSE: ! 359: longjmp(e.jbuf, 1); ! 360: /* NOTREACHED */ ! 361: case E_ERRH: ! 362: longjmp(e.jbuf, 1); ! 363: /* NOTREACHED */ ! 364: default: ! 365: quitenv(); ! 366: break; ! 367: } ! 368: } ! 369: ! 370: newenv(type) ! 371: { ! 372: register struct env *ep; ! 373: ! 374: ep = (struct env *) alloc(sizeof(*ep), ATEMP); ! 375: *ep = e; ! 376: ainit(&e.area); ! 377: e.type = type; ! 378: e.oenv = ep; ! 379: e.savefd = NULL; ! 380: e.temps = NULL; ! 381: } ! 382: ! 383: quitenv() ! 384: { ! 385: register struct env *ep; ! 386: register int fd; ! 387: ! 388: if ((ep = e.oenv) == NULL) ! 389: exit(exstat); /* exit child */ ! 390: if (e.loc != ep->loc) ! 391: popblock(); ! 392: if (e.savefd != NULL) ! 393: for (fd = 0; fd < NUFILE; fd++) ! 394: restfd(fd, e.savefd[fd]); ! 395: reclaim(); ! 396: e = *ep; ! 397: } ! 398: ! 399: /* remove temp files and free ATEMP Area */ ! 400: static void ! 401: reclaim() ! 402: { ! 403: register struct temp *tp; ! 404: ! 405: for (tp = e.temps; tp != NULL; tp = tp->next) ! 406: remove(tp->name); ! 407: e.temps = NULL; ! 408: afreeall(&e.area); ! 409: } ! 410: ! 411: void ! 412: aerror(ap, msg) ! 413: Area *ap; ! 414: Const char *msg; ! 415: { ! 416: errorf("alloc internal error: %s\n", msg); ! 417: } ! 418:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.