|
|
1.1 root 1: /*
2: * sh/main.c
3: * The Bourne shell.
4: * Main program, initialization and miscellaneous routines.
5: */
6:
7: #include <sys/param.h>
8: #include "sh.h"
9:
10: main(argc, argv, envp)
11: char *argv[];
12: char *envp[];
13: {
14: sarg0 = argc>0 ? argv[0] : "";
15: fakearg(0, argc, argv, envp);
16: if (argc>0 && argv[0][0]=='-') {
17: lgnflag = 1;
18: umask(ufmask=022);
19: } else if (argc>0 && argv[0][0]=='+') {
20: dflttrp(IBACK); /* for security, no <Ctrl-C> out of /etc/profile */
21: lgnflag = 2;
22: umask(ufmask=022);
23: } else {
24: umask(ufmask=umask(ufmask));
25: }
26:
27: if (setjmp(restart) != 0) {
28: /* reentry for shell command file execution */
29: fakearg(1, nargc, nargv, nenvp);
30: argc = nargc;
31: argv = nargv;
32: envp = nenvp;
33: cmdflag++;
34: nllflag = 0;
35: }
36:
37: shpid = getpid();
38: initvar(envp);
39: cleanup(1, NULL);
40: if (set(argc, argv, 1))
41: return(1);
42: if (cflag) {
43: if (sargp[0]==NULL) {
44: printe("No string for -c?");
45: return(1);
46: }
47: --sargc;
48: session(SARGS, *sargp++);
49: } else if (!sflag && !iflag && sargc!=0) {
50: sarg0 = *sargp++;
51: --sargc;
52: if (scmdp == NULL)
53: scmdp = sarg0;
54: session(SFILE, scmdp);
55: } else {
56: session(SSTR, stdin);
57: }
58: cleanup(2, NULL);
59: return (slret);
60: }
61:
62: /*
63: * Make the arg listing of ps come out right.
64: * f == 0, first entry, determine buffer limits.
65: * f != 0, later entry, fill buffer with lies.
66: */
67: fakearg(f, argc, argv, envp)
68: int f, argc;
69: char **argv, **envp;
70: {
71: static char *fbuf;
72: static int nbuf;
73: register int n;
74:
75: if (f == 0) {
76: fbuf = argv[0];
77: nbuf = 0;
78: if (envp != NULL && envp[0] != NULL) {
79: while (envp[1] != NULL)
80: envp += 1;
81: nbuf = envp[0] - fbuf + strlen(envp[0]) - 1;
82: } else if (argc > 0)
83: nbuf = argv[argc-1] - fbuf + strlen(argv[argc-1]) - 1;
84: } else {
85: if (fbuf == NULL || nbuf == 0)
86: return;
87: n = 0;
88: fbuf[0] = 0;
89: while (--argc > 0) {
90: argv += 1;
91: n += strlen(argv[0]) + 1;
92: if (n >= nbuf)
93: break;
94: strcat(fbuf, argv[0]);
95: strcat(fbuf, " ");
96: }
97: strcat(fbuf, "\1"); /* non-ascii terminator */
98: }
99: }
100:
101: /*
102: * Loop on input.
103: */
104: session(t, p)
105: register char *p;
106: {
107: SES s;
108: register int rcode;
109:
110: s.s_next = sesp;
111: sesp = &s;
112: s.s_bpp = savebuf();
113:
114: switch (s.s_type = t) {
115: case SARGS:
116: s.s_strp = p;
117: s.s_flag = 0;
118: break;
119: case SARGV:
120: s.s_argv = (char **) p;
121: if ((s.s_strp = s.s_argv[0]) == NULL)
122: return (0);
123: s.s_flag = 0;
124: break;
125: case SFILE:
126: s.s_strp = p;
127: if ((s.s_ifp = fopen(s.s_strp, "r")) == NULL) {
128: ecantopen(s.s_strp);
129: return (1);
130: }
131: s.s_flag = isatty(fileno(s.s_ifp)) && isatty(2);
132: break;
133: case SSTR:
134: s.s_strp = NULL;
135: s.s_ifp = (FILE *) p;
136: s.s_flag = isatty(fileno(s.s_ifp)) && isatty(2);
137: break;
138: }
139:
140: if (s.s_next == NULL) { /* Initial entry */
141: if (iflag)
142: s.s_flag = iflag;
143: else
144: iflag = s.s_flag;
145: if (lgnflag != 2)
146: dflttrp(IRDY); /* allow <Ctrl-C> unless "+sh" */
147: }
148:
149: /* Loop on input */
150: for (;;) {
151: rcode = setjmp(s.s_envl);
152: switch (rcode) {
153: case RSET: /* initial setjmp call */
154: switch (lgnflag) {
155: case 1: /* - sign invocation */
156: lgnflag = 0;
157: if (ffind("/etc", "profile", 4))
158: session(SFILE, duplstr(strt, 0));
159: recover(IPROF);
160: if (*vhome && ffind(vhome, ".profile", 4))
161: session(SFILE, duplstr(strt, 0));
162: break;
163: case 2: /* + sign invocation */
164: lgnflag = 0;
165: if (ffind("/etc", "profile", 4))
166: session(SFILE, duplstr(strt, 0));
167: recover(IPROF);
168: dflttrp(IRDY); /* allow <Ctrl-C> in SHELL */
169: return exshell( findvar("SHELL") );
170: }
171: checkmail();
172: comflag = 1;
173: errflag = 0;
174: recover(IRDY);
175: freebuf(s.s_bpp);
176: s.s_bpp = savebuf();
177: if (yyparse() != 0)
178: syntax();
179: case REOF:
180: recover(IRDY);
181: break;
182: case RCMD:
183: recover(IRDY);
184: s.s_con = NULL;
185: command(s.s_node);
186: if ((tflag && tflag++ >= 2))
187: break;
188: continue;
189: case RERR:
190: recover(IRDY);
191: if ( ! errflag)
192: syntax();
193: if ( ! iflag || (tflag && tflag++ >= 2))
194: break;
195: continue;
196: case RINT:
197: if (s.s_next != NULL) {
198: sesp = s.s_next;
199: reset(RINT);
200: NOTREACHED;
201: }
202: prpflag = 2;
203: if ( ! iflag || (tflag && tflag++ >= 2))
204: break;
205: continue;
206: case RUEXITS:
207: case RUABORT:
208: if (s.s_next != NULL) {
209: sesp = s.s_next;
210: reset(rcode);
211: NOTREACHED;
212: }
213: if (rcode == RUEXITS || !iflag || (tflag && tflag++ >= 2))
214: break;
215: continue;
216: case RNOSBRK:
217: case RSYSER:
218: case RBRKCON:
219: case RNOWAY:
220: default:
221: if (s.s_next!=NULL)
222: break;
223: if ( ! iflag || (tflag && tflag++ >= 2))
224: break;
225: continue;
226: }
227: break;
228: }
229: freebuf(s.s_bpp);
230: if (s.s_type == SFILE)
231: fclose(s.s_ifp);
232: if (s.s_next == NULL) {
233: sigintr(0);
234: recover(IRDY);
235: }
236: sesp = s.s_next;
237: return (slret);
238: }
239:
240: reset(f)
241: {
242: longjmp(sesp->s_envl, f);
243: NOTREACHED;
244: }
245:
246: /*
247: * Kludge cleanup.
248: */
249: cleanup(flag, file)
250: char *file;
251: {
252: static char *files[8];
253: static int nfiles = 0;
254: register char **pp;
255:
256: if (flag) {
257: for (pp=files; pp<files+8; pp+=1)
258: if (*pp != NULL) {
259: if (flag==2)
260: unlink(*pp);
261: sfree(*pp);
262: *pp = NULL;
263: }
264: nfiles = 0;
265: } else {
266: pp = files + nfiles;
267: if (*pp != NULL) {
268: unlink(*pp);
269: sfree(*pp);
270: }
271: *pp = duplstr(file, 1);
272: nfiles = (nfiles + 1) & 7;
273: }
274: }
275:
276: /*
277: * Make a temp file name.
278: */
279: char *
280: shtmp()
281: {
282: static char tmpfile[] = "/tmp/shXXXXXX";
283: static int tmpflag = 0;
284:
285: sprintf(tmpfile+6, "%05d%c", shpid, (tmpflag++%26) + 'a');
286: return (tmpfile);
287: }
288:
289: /*
290: * Print formatted.
291: */
292: /*
293: printv(av)
294: register char **av;
295: {
296: while (*av) prints("\t%s\n", *av++);
297: }
298: */
299:
300: prints(a1)
301: char *a1;
302: {
303: fprintf(stderr, "%r", &a1);
304: }
305:
306: /*
307: * Make a core dump in /tmp and longjmp back to session -
308: * there's a possibility we'll die horribly.
309: */
310: panic(i) register int i;
311: {
312: #ifdef PARANOID
313: register int f;
314:
315: if ((f=fork())==0) {
316: abort();
317: NOTREACHED;
318: }
319: waitc(f);
320: #endif
321: printe("Internal shell assertion %d failed", i);
322: reset(RNOWAY);
323: NOTREACHED;
324: }
325:
326: /*
327: * Print out an error message.
328: */
329: printe(a1)
330: char *a1;
331: {
332: errflag += 1;
333: if (! noeflag)
334: fprintf(stderr, "%r\n", &a1);
335: }
336:
337: /*
338: * Some familiar errors.
339: */
340: ecantopen(s) char *s; { printe("Cannot open %s", s); }
341: ecantfind(s) char *s; { printe("Cannot find %s", s); }
342: e2big(s) char *s; { printe("File to big to execute: %s", s); }
343: ecantmake(s) char *s; { printe("Cannot create %s", s); }
344: emisschar(c) { printe("Missing `%c'", c); }
345: ecantfdop() { printe("Fdopen failed"); }
346: enotdef(s) char *s; { printe("Cannot find variable %s", s); }
347: eillvar(s) char *s; { printe("Illegal variable name: %s", s); }
348: eredir() { printe("Illegal redirection"); }
349: etoolong() { printe("Argument too long: %.*s", STRSIZE, strt); }
350:
351: /*
352: * Don't print out an error message.
353: */
354: yyerror()
355: {
356: }
357:
358: /*
359: * print out the prompt given the prompt to write
360: */
361: prompt(vps)
362: char *vps;
363: {
364: prints("%s", vps);
365: #if RSX
366: fflush(stdout);
367: #endif
368: }
369:
370: /*
371: * Syntax error message - print line number and file if
372: * not interactive.
373: */
374: syntax()
375: {
376: if (sesp->s_type == SFILE) {
377: if (feof(sesp->s_ifp))
378: printe("%s: Syntax error at EOF", sesp->s_strp);
379: else
380: printe("%s: Syntax error in line %d", sesp->s_strp, yyline);
381: } else
382: printe("Syntax error");
383: }
384:
385: /* end of sh/main.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.