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