|
|
1.1 ! root 1: /* $Header$ */ ! 2: ! 3: /* ! 4: * Author: Peter J. Nicklin ! 5: */ ! 6: #include <ctype.h> ! 7: #include <signal.h> ! 8: #include <stdio.h> ! 9: #include <sys/param.h> ! 10: #include "bin.h" ! 11: #include "path.h" ! 12: #include "system.h" ! 13: #include "yesno.h" ! 14: ! 15: extern char **environ; /* global environment cell */ ! 16: static int Isfg; /* is process in forground? */ ! 17: static int Status; /* exit status */ ! 18: static int Want_to_quit; /* do we want to quit? */ ! 19: ! 20: /* ! 21: * execcmd() executes the COMMAND string in the current directory by ! 22: * forking the shell in the SHELL project environment variable. The ! 23: * PROJECT environment variable is updated before each fork in case ! 24: * the directory belongs to a subproject. If the forking process is in ! 25: * foreground, then an interrupt or quit signal may cause the shell ! 26: * to terminate. Returns non-zero error status if error. ! 27: */ ! 28: execcmd(project) ! 29: char *project; /* project root directory pathname */ ! 30: { ! 31: extern char *COMMAND; /* command string to be executed */ ! 32: extern char *SHELLNAME; /* name of command shell */ ! 33: extern char *SHELLPATH; /* pathname of command shell */ ! 34: extern int CSHELL; /* use csh or sh? */ ! 35: extern int CSHRC; /* execute .cshrc if csh shell */ ! 36: extern int ERRSTATUS; /* pexec error status */ ! 37: extern int IGNORE_BAD_EXIT; /* exit if shell doesn't return 0 */ ! 38: extern int PVINDEX; /* environ index for PROJECT variable */ ! 39: register int (*istat)(); /* interrupt status */ ! 40: register int (*qstat)(); /* quit status */ ! 41: static char pv[PATHSIZE+8] = "PROJECT="; ! 42: /* PROJECT env variable buffer */ ! 43: char *strcpy(); /* string copy */ ! 44: int isfg(); /* is a foreground job? */ ! 45: int onintr(); /* function called on interrupt */ ! 46: int pid; /* process id of forked child */ ! 47: int quit(); /* do we want to quit? */ ! 48: int w; /* process id of dead child */ ! 49: ! 50: /* ! 51: * The PROJECT environment variable is updated before being ! 52: * passed to a child process. This could be done by putting ! 53: * "setenv PROJECT xxxxxx" or "export PROJECT; PROJECT=xxxxxx" ! 54: * (depending on the shell) in the COMMAND string. ! 55: */ ! 56: strcpy(pv+8, project); ! 57: environ[PVINDEX] = pv; ! 58: ! 59: if ((pid = FORK()) == 0) ! 60: { ! 61: if (CSHELL && CSHRC == NO) ! 62: { ! 63: execl(SHELLPATH, SHELLNAME, "-f", "-c", COMMAND, 0); ! 64: } ! 65: else { ! 66: execl(SHELLPATH, SHELLNAME, "-c", COMMAND, 0); ! 67: } ! 68: _exit(127); ! 69: } ! 70: if ((Isfg = isfg()) == YES) ! 71: { ! 72: qstat = signal(SIGQUIT, SIG_IGN); ! 73: if ((istat = signal(SIGINT, SIG_IGN)) != SIG_IGN) ! 74: { ! 75: signal(SIGINT, onintr); ! 76: signal(SIGQUIT, onintr); ! 77: } ! 78: } ! 79: else { ! 80: istat = signal(SIGINT, SIG_IGN); ! 81: qstat = signal(SIGQUIT, SIG_IGN); ! 82: } ! 83: while ((w = wait(&Status)) != pid && w != -1) ! 84: continue; ! 85: if (w == -1) ! 86: Status = ERRSTATUS; ! 87: else { ! 88: Status >>= NBBY; ! 89: Status &= 0xff; ! 90: } ! 91: if (Want_to_quit) ! 92: { ! 93: if (quit() == YES) ! 94: exit(Status); ! 95: Want_to_quit = 0; ! 96: Status = 0; ! 97: } ! 98: if (Isfg == NO) /* if in foreground, we */ ! 99: { /* always want to catch */ ! 100: signal(SIGINT, istat); /* interrupts after they */ ! 101: signal(SIGQUIT, qstat); /* are first turned on */ ! 102: } ! 103: if (Status != 0 && IGNORE_BAD_EXIT == NO) ! 104: exit(Status); ! 105: return(Status); ! 106: } ! 107: ! 108: ! 109: ! 110: /* ! 111: * onintr() resets signals and indicates that the process may want to exit. ! 112: */ ! 113: onintr() ! 114: { ! 115: signal(SIGINT, onintr); ! 116: signal(SIGQUIT, onintr); ! 117: ! 118: Want_to_quit = 1; ! 119: } ! 120: ! 121: ! 122: ! 123: /* ! 124: * quit() returns YES if the process should exit, otherwise NO. ! 125: */ ! 126: quit() ! 127: { ! 128: register int (*istat)(); /* interrupt status */ ! 129: register int (*qstat)(); /* quit status */ ! 130: extern int NOQUERY; /* query user about quitting? */ ! 131: char *bp; /* buffer pointer */ ! 132: char buf[BUFSIZ]; /* input buffer */ ! 133: char *quitmsg; /* quit message string */ ! 134: int fd; /* I/O file descriptor */ ! 135: int strlen(); /* string length */ ! 136: ! 137: istat = signal(SIGINT, SIG_IGN); ! 138: qstat = signal(SIGQUIT, SIG_IGN); ! 139: ! 140: if (NOQUERY) ! 141: return(YES); ! 142: if ((fd = OPEN("/dev/tty", O_RDWR, 0600)) == -1) ! 143: { ! 144: pperror("/dev/tty"); ! 145: pxexit(); ! 146: } ! 147: quitmsg = "Do you really want to quit? [yn](y): "; ! 148: write(fd, quitmsg, strlen(quitmsg)); ! 149: if (read(fd, buf, BUFSIZ) <= 0) ! 150: return(YES); ! 151: for (bp = buf; isspace(*bp); bp++) ! 152: continue; ! 153: if (*bp != 'n') ! 154: return(YES); ! 155: close(fd); ! 156: ! 157: signal(SIGINT, istat); ! 158: signal(SIGQUIT, qstat); ! 159: ! 160: return(NO); ! 161: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.