bit operations generate longword reference which may reference the
[unix-history] / usr / src / bin / sh / main.c
CommitLineData
6c5bf7b4
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#ifndef lint
12char copyright[] =
13"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
14 All rights reserved.\n";
15#endif /* not lint */
16
17#ifndef lint
6f96c1c5 18static char sccsid[] = "@(#)main.c 5.4 (Berkeley) %G%";
6c5bf7b4
KB
19#endif /* not lint */
20
21#include <signal.h>
22#include <fcntl.h>
23#include "shell.h"
24#include "main.h"
25#include "mail.h"
26#include "options.h"
27#include "output.h"
28#include "parser.h"
29#include "nodes.h"
30#include "eval.h"
31#include "jobs.h"
32#include "input.h"
33#include "trap.h"
6c5bf7b4 34#include "var.h"
6c5bf7b4
KB
35#include "memalloc.h"
36#include "error.h"
37#include "init.h"
38#include "mystring.h"
39
40#define PROFILE 0
41
42int rootpid;
43int rootshell;
44STATIC union node *curcmd;
45STATIC union node *prevcmd;
46extern int errno;
47#if PROFILE
48short profile_buf[16384];
49extern int etext();
50#endif
51
52#ifdef __STDC__
53STATIC void read_profile(char *);
54char *getenv(char *);
55#else
56STATIC void read_profile();
57char *getenv();
58#endif
59
60
61/*
62 * Main routine. We initialize things, parse the arguments, execute
63 * profiles if we're a login shell, and then call cmdloop to execute
64 * commands. The setjmp call sets up the location to jump to when an
65 * exception occurs. When an exception occurs the variable "state"
66 * is used to figure out how far we had gotten.
67 */
68
69main(argc, argv) char **argv; {
70 struct jmploc jmploc;
71 struct stackmark smark;
72 volatile int state;
73 char *shinit;
74
75#if PROFILE
76 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
77#endif
78 state = 0;
79 if (setjmp(jmploc.loc)) {
80 /*
81 * When a shell procedure is executed, we raise the
82 * exception EXSHELLPROC to clean up before executing
83 * the shell procedure.
84 */
85 if (exception == EXSHELLPROC) {
86 rootpid = getpid();
87 rootshell = 1;
88 minusc = NULL;
89 state = 3;
90 } else if (state == 0 || iflag == 0 || ! rootshell)
91 exitshell(2);
92 reset();
93#if ATTY
94 if (exception == EXINT
95 && (! attyset() || equal(termval(), "emacs"))) {
96#else
97 if (exception == EXINT) {
98#endif
99 out2c('\n');
100 flushout(&errout);
101 }
102 popstackmark(&smark);
103 FORCEINTON; /* enable interrupts */
104 if (state == 1)
105 goto state1;
106 else if (state == 2)
107 goto state2;
efcbb576 108 else if (state == 3)
6c5bf7b4 109 goto state3;
efcbb576
MT
110 else
111 goto state4;
6c5bf7b4
KB
112 }
113 handler = &jmploc;
114#ifdef DEBUG
115 opentrace();
116 trputs("Shell args: "); trargs(argv);
117#endif
118 rootpid = getpid();
119 rootshell = 1;
120 init();
121 setstackmark(&smark);
122 procargs(argc, argv);
123 if (argv[0] && argv[0][0] == '-') {
124 state = 1;
125 read_profile("/etc/profile");
126state1:
127 state = 2;
128 read_profile(".profile");
efcbb576 129 }
6c5bf7b4
KB
130state2:
131 state = 3;
efcbb576
MT
132 if ((sflag || minusc) && (shinit = lookupvar("ENV")) != NULL &&
133 *shinit != '\0') {
134 state = 3;
135 read_profile(shinit);
136 }
137state3:
138 state = 4;
6c5bf7b4
KB
139 if (minusc) {
140 evalstring(minusc);
141 }
142 if (sflag || minusc == NULL) {
efcbb576 143state4: /* XXX ??? - why isn't this before the "if" statement */
6c5bf7b4
KB
144 cmdloop(1);
145 }
146#if PROFILE
147 monitor(0);
148#endif
149 exitshell(exitstatus);
150}
151
152
153/*
154 * Read and execute commands. "Top" is nonzero for the top level command
155 * loop; it turns on prompting if the shell is interactive.
156 */
157
158void
159cmdloop(top) {
160 union node *n;
161 struct stackmark smark;
162 int inter;
163 int numeof;
164
165 TRACE(("cmdloop(%d) called\n", top));
166 setstackmark(&smark);
167 numeof = 0;
168 for (;;) {
169 if (pendingsigs)
170 dotrap();
171 inter = 0;
172 if (iflag && top) {
173 inter++;
174 showjobs(1);
175 chkmail(0);
176 flushout(&output);
177 }
178 n = parsecmd(inter);
179#ifdef DEBUG
ddba57cd 180 /* showtree(n); */
6c5bf7b4
KB
181#endif
182 if (n == NEOF) {
efcbb576 183 if (Iflag == 0 || !top || numeof >= 50)
6c5bf7b4
KB
184 break;
185 out2str("\nUse \"exit\" to leave shell.\n");
186 numeof++;
187 } else if (n != NULL && nflag == 0) {
188 if (inter) {
189 INTOFF;
190 if (prevcmd)
191 freefunc(prevcmd);
192 prevcmd = curcmd;
193 curcmd = copyfunc(n);
194 INTON;
195 }
196 evaltree(n, 0);
197#ifdef notdef
198 if (exitstatus) /*DEBUG*/
199 outfmt(&errout, "Exit status 0x%X\n", exitstatus);
200#endif
201 }
202 popstackmark(&smark);
203 }
204 popstackmark(&smark); /* unnecessary */
205}
206
207
208
209/*
210 * Read /etc/profile or .profile. Return on error.
211 */
212
213STATIC void
214read_profile(name)
215 char *name;
216 {
217 int fd;
218
219 INTOFF;
220 if ((fd = open(name, O_RDONLY)) >= 0)
221 setinputfd(fd, 1);
222 INTON;
223 if (fd < 0)
224 return;
225 cmdloop(0);
226 popfile();
227}
228
229
230
231/*
232 * Read a file containing shell functions.
233 */
234
235void
236readcmdfile(name)
237 char *name;
238 {
239 int fd;
240
241 INTOFF;
242 if ((fd = open(name, O_RDONLY)) >= 0)
243 setinputfd(fd, 1);
244 else
245 error("Can't open %s", name);
246 INTON;
247 cmdloop(0);
248 popfile();
249}
250
251
252
253/*
254 * Take commands from a file. To be compatable we should do a path
255 * search for the file, but a path search doesn't make any sense.
256 */
257
258dotcmd(argc, argv) char **argv; {
259 exitstatus = 0;
260 if (argc >= 2) { /* That's what SVR2 does */
261 setinputfile(argv[1], 1);
262 commandname = argv[1];
263 cmdloop(0);
264 popfile();
265 }
266 return exitstatus;
267}
268
269
270exitcmd(argc, argv) char **argv; {
271 if (argc > 1)
272 exitstatus = number(argv[1]);
273 exitshell(exitstatus);
274}
275
276
277lccmd(argc, argv) char **argv; {
278 if (argc > 1) {
279 defun(argv[1], prevcmd);
280 return 0;
281 } else {
282 INTOFF;
283 freefunc(curcmd);
284 curcmd = prevcmd;
285 prevcmd = NULL;
286 INTON;
287 evaltree(curcmd, 0);
288 return exitstatus;
289 }
290}
291
292
293
294#ifdef notdef
295/*
296 * Should never be called.
297 */
298
299void
300exit(exitstatus) {
301 _exit(exitstatus);
302}
303#endif