|
|
1.1 root 1: /*
2: * sh/exec2.c
3: * Bourne shell.
4: * System part of execution.
5: */
6:
7: #include "sh.h"
8: #include <errno.h>
9: #include <sys/param.h>
10: #include <signal.h>
11: #include <sys/stat.h>
12: #include <fcntl.h>
13:
14: /*
15: * Wait for the given process to complete.
16: */
17: waitc(pid)
18: int pid;
19: {
20: register int f;
21: unsigned s;
22: register int w, n;
23: int (*ssig)();
24:
25: if (pid < 0)
26: f = -pid;
27: else
28: f = pid;
29: if ((ssig=signal(SIGINT, SIG_IGN)) != SIG_IGN)
30: signal(SIGINT, sigintr);
31: for (;;) {
32: if ((w=wait(&s)) >= 0) {
33: if (n = (s&0177)) {
34: if (n==SIGINT)
35: sigintr(n);
36: else if (n==SIGPIPE && spipe
37: && (w >= spipe && w <= f))
38: ;
39: else {
40: if (w != f)
41: prints("%d: ", w);
42: if (n==SIGSYS && (s&0200)==0)
43: prints("exec failed");
44: else if (n>0 && n<=NSIG)
45: prints("%s", signame[n]);
46: else
47: prints("status %d", n);
48: if (s & 0200)
49: prints(" -- core dumped");
50: prints("\n");
51: }
52: s = 200 + n;
53: } else
54: s >>= 8;
55: if (w == f) {
56: slret = s;
57: break;
58: }
59: } else if (errno==EINTR) {
60: if (pid > 0)
61: continue;
62: else {
63: slret = 0;
64: break;
65: }
66: } else if (errno==ECHILD) {
67: if (pid == 0)
68: slret = 0;
69: else
70: slret = ECHILD;
71: break;
72: } else {
73: panic(6);
74: NOTREACHED;
75: }
76: }
77: signal(SIGINT, ssig);
78: return (slret);
79: }
80:
81: /*
82: * Make an imperfect copy of ourself.
83: */
84: clone()
85: {
86: register int f;
87: register SES *sp;
88:
89: if ((f=fork()) < 0) {
90: prints("Try again\n");
91: reset(RSYSER);
92: NOTREACHED;
93: } else if (f == 0) {
94: nllflag = 1;
95: sflag = iflag = cflag = no1flag = lgnflag = 0;
96: slret = spipe = 0;
97: sp = sesp;
98: sp->s_con->c_next = NULL;
99:
100: /*
101: * Originally this function suppressed function definitions
102: * in child processes. This is wrong. Note that we have to
103: * detach the temporary-file stuff from the child functions,
104: * however, so that functions with here-documents work (as
105: * long as the top-level shell is alive, that is).
106: */
107: #if 1
108: subshell_shell_fns ();
109: #else
110: sh_fnp = NULL;
111: #endif
112:
113: while (sp) {
114: if (sp->s_type == SFILE)
115: fclose(sp->s_ifp);
116: sp = sp->s_next;
117: }
118: dflttrp(IFORK);
119: }
120: return (f);
121: }
122:
123: /*
124: * Open a pipe, panic on failure.
125: * Otherwise return as a clone.
126: */
127: pipeline(pv)
128: int *pv;
129: {
130: if (pipe(pv) < 0) {
131: prints("Pipe failed\n");
132: reset(RSYSER);
133: NOTREACHED;
134: }
135: return (clone());
136: }
137:
138: /*
139: * Try to execute a file in several ways.
140: * A return is always an error.
141: * Used by exec in inline.
142: */
143: flexec()
144: {
145: ffind(NULL);
146: while (ffind(vpath, *nargv, 1)) {
147: execve(strt, nargv, nenvp);
148: if (errno==ENOEXEC) {
149: scmdp = duplstr(strt, 0);
150: nargc += 1;
151: nargv -= 1;
152: nargv = vdupl(nargv);
153: nenvp = vdupl(nenvp);
154: while (sesp) {
155: freebuf(sesp->s_bpp);
156: sesp = sesp->s_next;
157: }
158: longjmp(restart, 1);
159: }
160: if (errno==E2BIG) {
161: e2big(nargv[0]);
162: return(-1);
163: }
164: }
165: ecantfind(nargv[0]);
166: return (-1);
167: }
168:
169: ALLOC_COUNT (undo)
170:
171: /*
172: * Process a redirection vector.
173: * Abort and return -1 at the first failure, return 0 for success.
174: *
175: * NB: In ordr to support redirection of builtins, an extra argument to this
176: * function has been addded. If undo is NULL, things remain as before, but if
177: * non-NULL it is taken to be the head of a list of undo items. As the list of
178: * redirections is processed, undo entries will be added to the head of the
179: * list, so that the caller will see the list in the appropriate order for
180: * undoing the redirections.
181: */
182: redirect(iovp, undo)
183: char **iovp;
184: REDIR_UNDO ** undo;
185: {
186: register char **iopp;
187: register char *io;
188: register int op;
189: int u1, u2;
190: REDIR_UNDO * undo_node;
191:
192: for (iopp = iovp;(io = *iopp++)!=NULL; ) {
193: if (class(*io, MDIGI))
194: u1 = *io++ - '0';
195: else
196: u1 = *io=='<' ? 0 : 1;
197:
198: if (undo) {
199: /*
200: * Create and link in the undo node now. Stash away a
201: * spare copy of the original fd as well. Note that
202: * this may cause semantic changes in attempts to
203: * redirect from fds that would otherwise be closed,
204: * but that error was never diagnosed before anyway...
205: */
206:
207: ALLOC_ALLOC (undo);
208: undo_node = (REDIR_UNDO *) salloc (sizeof (REDIR_UNDO));
209: undo_node->ru_next = * undo;
210: undo_node->ru_oldfd = u1;
211: if ((undo_node->ru_newfd = dup (u1)) == -1) {
212: if (errno != EBADF)
213: eredirundo ();
214: } else {
215: fcntl (undo_node->ru_newfd, F_SETFD,
216: fcntl (undo_node->ru_newfd, F_GETFD,
217: 0) | FD_CLOEXEC);
218: }
219: * undo = undo_node;
220: } else
221: undo_node = NULL;
222: for (op=0; ; io+=1)
223: if (*io=='>')
224: op += 1;
225: else if (*io=='<')
226: op -= 1;
227: else
228: break;
229: if (*io++ == '&') {
230: if (op != 1 && op != -1) {
231: panic(7);
232: NOTREACHED;
233: }
234: u2 = *io++;
235: if (u2 == '-') {
236: close(u1);
237: continue;
238: } else if (!class(u2, MDIGI)) {
239: eredir();
240: return (-1);
241: } else {
242: u2 -= '0';
243: dup2(u2, u1);
244: continue;
245: }
246: }
247: for (io-=1; *io==' '||*io=='\t'; io+=1);
248: switch (op) {
249: case -2: /* Unquoted here */
250: /* Fall through */
251: case -1: /* Input file, quoted here */
252: if ((u2 = open(io, 0)) < 0) {
253: ecantopen(io);
254: return (-1);
255: }
256: if (op == -2 && (u2 = evalhere(u2)) < 0)
257: return (-1);
258: dup2(u2, u1);
259: close(u2);
260: continue;
261: case 2: /* Append to output */
262: if ((u2 = open(io, 1)) >= 0) {
263: lseek(u2, 0L, 2);
264: dup2(u2, u1);
265: close(u2);
266: continue;
267: } /* else fall through */
268: case 1: /* Output file */
269: if ((u2 = creat(io, 0666)) < 0) {
270: ecantmake(io);
271: return (-1);
272: }
273: dup2(u2, u1);
274: close(u2);
275: continue;
276: default:
277: panic(8);
278: NOTREACHED;
279: }
280: }
281: return (0);
282: }
283:
284: /*
285: * Undo a redirection sequence, reclaiming all the space for the undo nodes.
286: */
287: redirundo (undo)
288: REDIR_UNDO ** undo;
289: {
290: REDIR_UNDO * undo_node;
291:
292: while ((undo_node = * undo) != NULL) {
293: * undo = undo_node->ru_next;
294: if (undo_node->ru_newfd == -1)
295: close (undo_node->ru_oldfd);
296: else {
297: dup2 (undo_node->ru_newfd, undo_node->ru_oldfd);
298: close (undo_node->ru_newfd);
299: }
300: ALLOC_FREE (undo);
301: sfree (undo_node);
302: }
303: return 0;
304: }
305:
306:
307: #ifdef NAMEPIPE
308: /*
309: * Create a named pipe.
310: */
311: npipe(np)
312: register NODE *np;
313: {
314: register char *tmp;
315: register int f;
316: char *tvec[2];
317:
318: tmp = shtmp();
319: mknod(tmp, S_IFPIP, 0);
320: if ((f = clone()) == 0) {
321: if (np->n_type==NRPIPE)
322: strt[0] = '<';
323: else
324: strt[0] = '>';
325: strt[1] = '\0';
326: tvec[0] = strcat(strt, tmp);
327: tvec[1] = NULL;
328: redirect(tvec, NULL);
329: command(np->n_auxp);
330: exit(slret);
331: NOTREACHED;
332: }
333: remember_temp (tmp);
334: strcpy(strt, tmp);
335: return;
336: }
337: #endif
338:
339: /*
340: * Search a path, perhaps repeatedly, for a file with access mode.
341: * Is called with paths == NULL to reset pointers.
342: * UGLY, but it works.
343: */
344: ffind(paths, file, mode)
345: char *paths, *file;
346: {
347: register char c, *cp1, *cp2;
348: static char *fp, *ff, *fcp;
349:
350: if (paths==NULL) {
351: fp = ff = fcp = NULL;
352: return (0);
353: }
354: if (ff!=file) {
355: fp = fcp = paths;
356: ff = file;
357: if (index(ff, '/')!=NULL)
358: fcp = "";
359: }
360: for (c=':'; c==':'; ) {
361: cp1 = fcp;
362: cp2 = strt;
363: while (*cp1 && *cp1!=':')
364: *cp2++ = *cp1++;
365: if (cp2 != strt)
366: *cp2++ = '/';
367: c = *cp1++;
368: fcp = cp1;
369: cp1 = ff;
370: while (*cp2++ = *cp1++);
371: if (access(strt, mode)>=0)
372: return (1);
373: }
374: return (0);
375: }
376:
377: /*
378: * execute a non standard shell.
379: */
380: exshell(vp) VAR *vp;
381: {
382: char *vshell;
383: register char *p;
384:
385: vshell = vp->v_strp;
386: while (*vshell && *vshell++ != '=');
387: /* Construct -name argv[0] */
388: if ((p = rindex(vshell, '/')) != NULL)
389: p += 1;
390: else
391: p = vshell;
392: strcpy(strt, "-");
393: strcat(strt, p);
394: /* Construct argv */
395: nargv = makargl();
396: nargv = addargl(nargv, "sh");
397: nargv = addargl(nargv, duplstr(strt, 0));
398: nargc = 2;
399: /* Construct envp */
400: nenvp = makargl();
401: nenvp = envlvar(nenvp);
402: /* Try exec */
403: execve(vshell, nargv+1, nenvp);
404:
405: if (errno==ENOEXEC) {
406: fakearg(1, nargc, nargv, nenvp);
407: sargc = 0;
408: sargp = nargv+2;
409: sarg0 = nargv[1];
410: nllflag = 0;
411: return session(SFILE, vshell);
412: }
413: fprintf(stderr, "No shell: %s\n", vshell);
414: exit(1);
415: }
416:
417: /*
418: * Check to see if we have mail.
419: */
420: checkmail()
421: {
422: static long mailsize = -1;
423: struct stat sbuf;
424:
425: if (*vmail == '\0')
426: return;
427: if (stat(vmail, &sbuf)<0) {
428: mailsize = 0;
429: } else {
430: if (sbuf.st_size != 0
431: && sbuf.st_size > mailsize) {
432: if (mailsize == -1)
433: prints("You have mail.\n");
434: else
435: prints("You have new mail.\n");
436: }
437: mailsize = sbuf.st_size;
438: }
439: }
440:
441: /* end of sh/exec2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.