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: }
Defined functions
quit
defined in line
126; used 2 times
Defined variables
Isfg
defined in line
16; used 2 times