#include "rc.h" #include "parse.h" #include "exec.h" #include #include // ----------------------------------------------------------------------- // globals Thread *runner = nil; Shell shell = { 0 }; // ----------------------------------------------------------------------- // functions void initshell(int *iflag) { if((*iflag=isatty(0))){ while(tcgetpgrp(0) != (shell.pid = getpgrp())) kill(-shell.pid, SIGTTIN); /* ignore job control signals */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); /* NOTE: if SIGCHLD is set to SIG_IGN then * 1. children that terminate do not become zombies * 2. call a to wait() will block until all children have terminated * 3. the call to wait will fail with errno == ECHILD * see for discussion: * https://stackoverflow.com/questions/1608017/no-child-process-error-from-waitpid-when-waiting-for-process-group */ // signal(SIGCHLD, SIG_IGN); /* take control */ shell.pid = getpid(); if(setpgid(shell.pid, shell.pid)<0) fatal("could not put shell in its own process group"); tcsetpgrp(shell.pid, shell.pid); } } // ----------------------------------------------------------------------- // main point of entry static void usage(void) { print(shell.err, "usage: %s [-cei] [file]", argv0); exit(2); } int main(int argc, char *argv[]) { int flag; char *exe, *cmd = nil; shell.err = openfd(2); initenv(); initpath(); initkeywords(); inithistory(); initshell(&flag); ARGBEGIN{ case 'e': shell.noerror = 1; break; case 'i': shell.interactive = 1; break; case 'I': shell.interactive = 0; break; case 'c': cmd = EARGF(usage()); panicf("not implemented"); break; default: usage(); }ARGEND; if(!argc){ shell.interactive |= flag; exe = "/dev/stdin"; }else exe = *argv++, argc--; initlexer(shell.interactive); /* enablevi(); */ xboot(exe, argc, argv); /* unreachable */ }