1
/* $NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $ */
4
* Copyright (c) 1991, 1993
5
* The Regents of the University of California. All rights reserved.
7
* This code is derived from software contributed to Berkeley by
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of the University nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
#include <sys/cdefs.h>
42
#define __COPYRIGHT(arg)
45
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
46
The Regents of the University of California. All rights reserved.\n");
51
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
53
__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
93
STATIC union node *curcmd;
94
STATIC union node *prevcmd;
96
short profile_buf[16384];
100
STATIC void read_profile(const char *);
101
STATIC char *find_dot_file(char *);
102
int main(int, char **);
105
* Main routine. We initialize things, parse the arguments, execute
106
* profiles if we're a login shell, and then call cmdloop to execute
107
* commands. The setjmp call sets up the location to jump to when an
108
* exception occurs. When an exception occurs the variable "state"
109
* is used to figure out how far we had gotten.
113
main(int argc, char **argv)
115
struct jmploc jmploc;
116
struct stackmark smark;
121
setlocale(LC_ALL, "");
125
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
128
if (setjmp(jmploc.loc)) {
130
* When a shell procedure is executed, we raise the
131
* exception EXSHELLPROC to clean up before executing
132
* the shell procedure.
143
exitstatus = exerrno;
154
if (exception != EXSHELLPROC) {
155
if (state == 0 || iflag == 0 || ! rootshell)
156
exitshell(exitstatus);
159
if (exception == EXINT
161
&& (! attyset() || equal(termval(), "emacs"))
167
popstackmark(&smark);
168
FORCEINTON; /* enable interrupts */
184
trputs("Shell args: "); trargs(argv);
189
setstackmark(&smark);
190
procargs(argc, argv);
191
if (argv[0] && argv[0][0] == '-') {
193
read_profile("/etc/profile");
196
read_profile(".profile");
200
if (getuid() == geteuid() && getgid() == getegid()) {
201
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
203
read_profile(shinit);
208
if (sflag == 0 || minusc) {
209
static int sigs[] = {
210
SIGINT, SIGQUIT, SIGHUP,
216
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
219
for (i = 0; i < SIGSSIZE; i++)
220
setsignal(sigs[i], 0);
224
evalstring(minusc, 0);
226
if (sflag || minusc == NULL) {
227
state4: /* XXX ??? - why isn't this before the "if" statement */
233
exitshell(exitstatus);
239
* Read and execute commands. "Top" is nonzero for the top level command
240
* loop; it turns on prompting if the shell is interactive.
247
struct stackmark smark;
251
TRACE(("cmdloop(%d) called\n", top));
252
setstackmark(&smark);
259
showjobs(out2, SHOW_CHANGED);
266
/* showtree(n); DEBUG */
268
if (!top || numeof >= 50)
270
if (!stoppedjobs()) {
273
out2str("\nUse \"exit\" to leave shell.\n");
276
} else if (n != NULL && nflag == 0) {
277
job_warning = (job_warning == 2) ? 1 : 0;
281
popstackmark(&smark);
282
setstackmark(&smark);
283
if (evalskip == SKIPFILE) {
288
popstackmark(&smark);
294
* Read /etc/profile or .profile. Return on error.
298
read_profile(const char *name)
305
if ((fd = open(name, O_RDONLY)) >= 0)
310
/* -q turns off -x and -v just when executing init files */
313
xflag = 0, xflag_set = 1;
315
vflag = 0, vflag_set = 1;
330
* Read a file containing shell functions.
334
readcmdfile(char *name)
339
if ((fd = open(name, O_RDONLY)) >= 0)
342
error("Can't open %s", name);
351
* Take commands from a file. To be compatible we should do a path
352
* search for the file, which is necessary to find sub-commands.
357
find_dot_file(char *basename)
360
const char *path = pathval();
363
/* don't try this for absolute or relative paths */
364
if (strchr(basename, '/'))
367
while ((fullname = padvance(&path, basename)) != NULL) {
368
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
370
* Don't bother freeing here, since it will
371
* be freed by the caller.
378
/* not found in the PATH */
379
error("%s: not found", basename);
384
dotcmd(int argc, char **argv)
388
if (argc >= 2) { /* That's what SVR2 does */
390
struct stackmark smark;
392
setstackmark(&smark);
393
fullname = find_dot_file(argv[1]);
394
setinputfile(fullname, 1);
395
commandname = fullname;
398
popstackmark(&smark);
405
exitcmd(int argc, char **argv)
410
exitstatus = number(argv[1]);
411
exitshell(exitstatus);