xref: /titanic_51/usr/src/cmd/sh/main.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate /*
35*7c478bd9Sstevel@tonic-gate  * UNIX shell
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #include	"defs.h"
39*7c478bd9Sstevel@tonic-gate #include	"sym.h"
40*7c478bd9Sstevel@tonic-gate #include	"timeout.h"
41*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
43*7c478bd9Sstevel@tonic-gate #include	<sys/wait.h>
44*7c478bd9Sstevel@tonic-gate #include	"dup.h"
45*7c478bd9Sstevel@tonic-gate #include	"sh_policy.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #ifdef RES
48*7c478bd9Sstevel@tonic-gate #include	<sgtty.h>
49*7c478bd9Sstevel@tonic-gate #endif
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate pid_t mypid, mypgid, mysid;
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate static BOOL	beenhere = FALSE;
54*7c478bd9Sstevel@tonic-gate unsigned char		tmpout[20] = "/tmp/sh-";
55*7c478bd9Sstevel@tonic-gate struct fileblk	stdfile;
56*7c478bd9Sstevel@tonic-gate struct fileblk *standin = &stdfile;
57*7c478bd9Sstevel@tonic-gate int mailchk = 0;
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static unsigned char	*mailp;
60*7c478bd9Sstevel@tonic-gate static long	*mod_time = 0;
61*7c478bd9Sstevel@tonic-gate static BOOL login_shell = FALSE;
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #if vax
64*7c478bd9Sstevel@tonic-gate char **execargs = (char **)(0x7ffffffc);
65*7c478bd9Sstevel@tonic-gate #endif
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #if pdp11
68*7c478bd9Sstevel@tonic-gate char **execargs = (char **)(-2);
69*7c478bd9Sstevel@tonic-gate #endif
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate static int	exfile();
73*7c478bd9Sstevel@tonic-gate extern unsigned char 	*simple();
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate main(c, v, e)
77*7c478bd9Sstevel@tonic-gate int	c;
78*7c478bd9Sstevel@tonic-gate char	*v[];
79*7c478bd9Sstevel@tonic-gate char	*e[];
80*7c478bd9Sstevel@tonic-gate {
81*7c478bd9Sstevel@tonic-gate 	register int	rflag = ttyflg;
82*7c478bd9Sstevel@tonic-gate 	int		rsflag = 1;	/* local restricted flag */
83*7c478bd9Sstevel@tonic-gate 	register unsigned char *flagc = flagadr;
84*7c478bd9Sstevel@tonic-gate 	struct namnod	*n;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	mypid = getpid();
87*7c478bd9Sstevel@tonic-gate 	mypgid = getpgid(mypid);
88*7c478bd9Sstevel@tonic-gate 	mysid = getsid(mypid);
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	/*
91*7c478bd9Sstevel@tonic-gate 	 * Do locale processing only if /usr is mounted.
92*7c478bd9Sstevel@tonic-gate 	 */
93*7c478bd9Sstevel@tonic-gate 	localedir_exists = (access(localedir, F_OK) == 0);
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	/*
96*7c478bd9Sstevel@tonic-gate 	 * initialize storage allocation
97*7c478bd9Sstevel@tonic-gate 	 */
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	if (stakbot == 0) {
100*7c478bd9Sstevel@tonic-gate 	addblok((unsigned)0);
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	/*
104*7c478bd9Sstevel@tonic-gate 	 * If the first character of the last path element of v[0] is "-"
105*7c478bd9Sstevel@tonic-gate 	 * (ex. -sh, or /bin/-sh), this is a login shell
106*7c478bd9Sstevel@tonic-gate 	 */
107*7c478bd9Sstevel@tonic-gate 	if (*simple(v[0]) == '-') {
108*7c478bd9Sstevel@tonic-gate 		signal(SIGXCPU, SIG_DFL);
109*7c478bd9Sstevel@tonic-gate 		signal(SIGXFSZ, SIG_DFL);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 		/*
112*7c478bd9Sstevel@tonic-gate 		 * As the previous comment states, this is a login shell.
113*7c478bd9Sstevel@tonic-gate 		 * Therefore, we set the login_shell flag to explicitly
114*7c478bd9Sstevel@tonic-gate 		 * indicate this condition.
115*7c478bd9Sstevel@tonic-gate 		 */
116*7c478bd9Sstevel@tonic-gate 		login_shell = TRUE;
117*7c478bd9Sstevel@tonic-gate 	}
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	stdsigs();
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * set names from userenv
123*7c478bd9Sstevel@tonic-gate 	 */
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	setup_env();
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	/*
128*7c478bd9Sstevel@tonic-gate 	 * LC_MESSAGES is set here so that early error messages will
129*7c478bd9Sstevel@tonic-gate 	 * come out in the right style.
130*7c478bd9Sstevel@tonic-gate 	 * Note that LC_CTYPE is done later on and is *not*
131*7c478bd9Sstevel@tonic-gate 	 * taken from the previous environ
132*7c478bd9Sstevel@tonic-gate 	 */
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	/*
135*7c478bd9Sstevel@tonic-gate 	 * Do locale processing only if /usr is mounted.
136*7c478bd9Sstevel@tonic-gate 	 */
137*7c478bd9Sstevel@tonic-gate 	if (localedir_exists)
138*7c478bd9Sstevel@tonic-gate 		(void) setlocale(LC_ALL, "");
139*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
140*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
141*7c478bd9Sstevel@tonic-gate #endif
142*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/*
145*7c478bd9Sstevel@tonic-gate 	 * This is a profile shell if the simple name of argv[0] is
146*7c478bd9Sstevel@tonic-gate 	 * pfsh or -pfsh
147*7c478bd9Sstevel@tonic-gate 	 */
148*7c478bd9Sstevel@tonic-gate 	if (c > 0 && (eq("pfsh", simple(*v)) || eq("-pfsh", simple(*v)))) {
149*7c478bd9Sstevel@tonic-gate 		flags |= pfshflg;
150*7c478bd9Sstevel@tonic-gate 		secpolicy_init();
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	/*
154*7c478bd9Sstevel@tonic-gate 	 * 'rsflag' is zero if SHELL variable is
155*7c478bd9Sstevel@tonic-gate 	 *  set in environment and
156*7c478bd9Sstevel@tonic-gate 	 *  the simple file part of the value.
157*7c478bd9Sstevel@tonic-gate 	 *  is rsh
158*7c478bd9Sstevel@tonic-gate 	 */
159*7c478bd9Sstevel@tonic-gate 	if (n = findnam("SHELL"))
160*7c478bd9Sstevel@tonic-gate 	{
161*7c478bd9Sstevel@tonic-gate 		if (eq("rsh", simple(n->namval)))
162*7c478bd9Sstevel@tonic-gate 			rsflag = 0;
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/*
166*7c478bd9Sstevel@tonic-gate 	 * a shell is also restricted if the simple name of argv(0) is
167*7c478bd9Sstevel@tonic-gate 	 * rsh or -rsh in its simple name
168*7c478bd9Sstevel@tonic-gate 	 */
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate #ifndef RES
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (c > 0 && (eq("rsh", simple(*v)) || eq("-rsh", simple(*v))))
173*7c478bd9Sstevel@tonic-gate 		rflag = 0;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate #endif
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	if (eq("jsh", simple(*v)) || eq("-jsh", simple(*v)))
178*7c478bd9Sstevel@tonic-gate 		flags |= monitorflg;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	hcreate();
181*7c478bd9Sstevel@tonic-gate 	set_dotpath();
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	/*
185*7c478bd9Sstevel@tonic-gate 	 * look for options
186*7c478bd9Sstevel@tonic-gate 	 * dolc is $#
187*7c478bd9Sstevel@tonic-gate 	 */
188*7c478bd9Sstevel@tonic-gate 	dolc = options(c, v);
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	if (dolc < 2)
191*7c478bd9Sstevel@tonic-gate 	{
192*7c478bd9Sstevel@tonic-gate 		flags |= stdflg;
193*7c478bd9Sstevel@tonic-gate 		{
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 			while (*flagc)
196*7c478bd9Sstevel@tonic-gate 				flagc++;
197*7c478bd9Sstevel@tonic-gate 			*flagc++ = STDFLG;
198*7c478bd9Sstevel@tonic-gate 			*flagc = 0;
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	if ((flags & stdflg) == 0)
202*7c478bd9Sstevel@tonic-gate 		dolc--;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	if ((flags & privflg) == 0) {
205*7c478bd9Sstevel@tonic-gate 		register uid_t euid;
206*7c478bd9Sstevel@tonic-gate 		register gid_t egid;
207*7c478bd9Sstevel@tonic-gate 		register uid_t ruid;
208*7c478bd9Sstevel@tonic-gate 		register gid_t rgid;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 		/*
211*7c478bd9Sstevel@tonic-gate 		 * Determine all of the user's id #'s for this process and
212*7c478bd9Sstevel@tonic-gate 		 * then decide if this shell is being entered as a result
213*7c478bd9Sstevel@tonic-gate 		 * of a fork/exec.
214*7c478bd9Sstevel@tonic-gate 		 * If the effective uid/gid do NOT match and the euid/egid
215*7c478bd9Sstevel@tonic-gate 		 * is < 100 and the egid is NOT 1, reset the uid and gid to
216*7c478bd9Sstevel@tonic-gate 		 * the user originally calling this process.
217*7c478bd9Sstevel@tonic-gate 		 */
218*7c478bd9Sstevel@tonic-gate 		euid = geteuid();
219*7c478bd9Sstevel@tonic-gate 		ruid = getuid();
220*7c478bd9Sstevel@tonic-gate 		egid = getegid();
221*7c478bd9Sstevel@tonic-gate 		rgid = getgid();
222*7c478bd9Sstevel@tonic-gate 		if ((euid != ruid) && (euid < 100))
223*7c478bd9Sstevel@tonic-gate 			setuid(ruid);   /* reset the uid to the orig user */
224*7c478bd9Sstevel@tonic-gate 		if ((egid != rgid) && ((egid < 100) && (egid != 1)))
225*7c478bd9Sstevel@tonic-gate 			setgid(rgid);   /* reset the gid to the orig user */
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	dolv = (unsigned char **)v + c - dolc;
229*7c478bd9Sstevel@tonic-gate 	dolc--;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/*
232*7c478bd9Sstevel@tonic-gate 	 * return here for shell file execution
233*7c478bd9Sstevel@tonic-gate 	 * but not for parenthesis subshells
234*7c478bd9Sstevel@tonic-gate 	 */
235*7c478bd9Sstevel@tonic-gate 	if (setjmp(subshell)) {
236*7c478bd9Sstevel@tonic-gate 		freejobs();
237*7c478bd9Sstevel@tonic-gate 		flags |= subsh;
238*7c478bd9Sstevel@tonic-gate 	}
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	/*
241*7c478bd9Sstevel@tonic-gate 	 * number of positional parameters
242*7c478bd9Sstevel@tonic-gate 	 */
243*7c478bd9Sstevel@tonic-gate 	replace(&cmdadr, dolv[0]);	/* cmdadr is $0 */
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	/*
246*7c478bd9Sstevel@tonic-gate 	 * set pidname '$$'
247*7c478bd9Sstevel@tonic-gate 	 */
248*7c478bd9Sstevel@tonic-gate 	assnum(&pidadr, (long)mypid);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/*
251*7c478bd9Sstevel@tonic-gate 	 * set up temp file names
252*7c478bd9Sstevel@tonic-gate 	 */
253*7c478bd9Sstevel@tonic-gate 	settmp();
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	/*
256*7c478bd9Sstevel@tonic-gate 	 * default internal field separators
257*7c478bd9Sstevel@tonic-gate 	 * Do not allow importing of IFS from parent shell.
258*7c478bd9Sstevel@tonic-gate 	 * setup_env() may have set anything from parent shell to IFS.
259*7c478bd9Sstevel@tonic-gate 	 * Always set the default ifs to IFS.
260*7c478bd9Sstevel@tonic-gate 	 */
261*7c478bd9Sstevel@tonic-gate 	assign(&ifsnod, sptbnl);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	dfault(&mchknod, MAILCHECK);
264*7c478bd9Sstevel@tonic-gate 	mailchk = stoi(mchknod.namval);
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/* initialize OPTIND for getopt */
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	n = lookup("OPTIND");
269*7c478bd9Sstevel@tonic-gate 	assign(n, "1");
270*7c478bd9Sstevel@tonic-gate 	/*
271*7c478bd9Sstevel@tonic-gate 	 * make sure that option parsing starts
272*7c478bd9Sstevel@tonic-gate 	 * at first character
273*7c478bd9Sstevel@tonic-gate 	 */
274*7c478bd9Sstevel@tonic-gate 	_sp = 1;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	/* initialize multibyte information */
277*7c478bd9Sstevel@tonic-gate 	setwidth();
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	if ((beenhere++) == FALSE)	/* ? profile */
280*7c478bd9Sstevel@tonic-gate 	{
281*7c478bd9Sstevel@tonic-gate 		if ((login_shell == TRUE) && (flags & privflg) == 0) {
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 			/* system profile */
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate #ifndef RES
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 			if ((input = pathopen(nullstr, sysprofile)) >= 0)
288*7c478bd9Sstevel@tonic-gate 				exfile(rflag);		/* file exists */
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate #endif
291*7c478bd9Sstevel@tonic-gate 			/* user profile */
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 			if ((input = pathopen(homenod.namval, profile)) >= 0)
294*7c478bd9Sstevel@tonic-gate 			{
295*7c478bd9Sstevel@tonic-gate 				exfile(rflag);
296*7c478bd9Sstevel@tonic-gate 				flags &= ~ttyflg;
297*7c478bd9Sstevel@tonic-gate 			}
298*7c478bd9Sstevel@tonic-gate 		}
299*7c478bd9Sstevel@tonic-gate 		if (rsflag == 0 || rflag == 0) {
300*7c478bd9Sstevel@tonic-gate 			if ((flags & rshflg) == 0) {
301*7c478bd9Sstevel@tonic-gate 				while (*flagc)
302*7c478bd9Sstevel@tonic-gate 					flagc++;
303*7c478bd9Sstevel@tonic-gate 				*flagc++ = 'r';
304*7c478bd9Sstevel@tonic-gate 				*flagc = '\0';
305*7c478bd9Sstevel@tonic-gate 			}
306*7c478bd9Sstevel@tonic-gate 			flags |= rshflg;
307*7c478bd9Sstevel@tonic-gate 		}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 		/*
310*7c478bd9Sstevel@tonic-gate 		 * open input file if specified
311*7c478bd9Sstevel@tonic-gate 		 */
312*7c478bd9Sstevel@tonic-gate 		if (comdiv)
313*7c478bd9Sstevel@tonic-gate 		{
314*7c478bd9Sstevel@tonic-gate 			estabf(comdiv);
315*7c478bd9Sstevel@tonic-gate 			input = -1;
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 		else
318*7c478bd9Sstevel@tonic-gate 		{
319*7c478bd9Sstevel@tonic-gate 			if (flags & stdflg) {
320*7c478bd9Sstevel@tonic-gate 				input = 0;
321*7c478bd9Sstevel@tonic-gate 			} else {
322*7c478bd9Sstevel@tonic-gate 			/*
323*7c478bd9Sstevel@tonic-gate 			 * If the command file specified by 'cmdadr'
324*7c478bd9Sstevel@tonic-gate 			 * doesn't exist, chkopen() will fail calling
325*7c478bd9Sstevel@tonic-gate 			 * exitsh(). If this is a login shell and
326*7c478bd9Sstevel@tonic-gate 			 * the $HOME/.profile file does not exist, the
327*7c478bd9Sstevel@tonic-gate 			 * above statement "flags &= ~ttyflg" does not
328*7c478bd9Sstevel@tonic-gate 			 * get executed and this makes exitsh() call
329*7c478bd9Sstevel@tonic-gate 			 * longjmp() instead of exiting. longjmp() will
330*7c478bd9Sstevel@tonic-gate 			 * return to the location specified by the last
331*7c478bd9Sstevel@tonic-gate 			 * active jmpbuffer, which is the one set up in
332*7c478bd9Sstevel@tonic-gate 			 * the function exfile() called after the system
333*7c478bd9Sstevel@tonic-gate 			 * profile file is executed (see lines above).
334*7c478bd9Sstevel@tonic-gate 			 * This would cause an infinite loop, because
335*7c478bd9Sstevel@tonic-gate 			 * chkopen() will continue to fail and exitsh()
336*7c478bd9Sstevel@tonic-gate 			 * to call longjmp(). To make exitsh() exit instead
337*7c478bd9Sstevel@tonic-gate 			 * of calling longjmp(), we then set the flag forcexit
338*7c478bd9Sstevel@tonic-gate 			 * at this stage.
339*7c478bd9Sstevel@tonic-gate 			 */
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 				flags |= forcexit;
342*7c478bd9Sstevel@tonic-gate 				input = chkopen(cmdadr, 0);
343*7c478bd9Sstevel@tonic-gate 				flags &= ~forcexit;
344*7c478bd9Sstevel@tonic-gate 			}
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate #ifdef ACCT
347*7c478bd9Sstevel@tonic-gate 			if (input != 0)
348*7c478bd9Sstevel@tonic-gate 				preacct(cmdadr);
349*7c478bd9Sstevel@tonic-gate #endif
350*7c478bd9Sstevel@tonic-gate 			comdiv--;
351*7c478bd9Sstevel@tonic-gate 		}
352*7c478bd9Sstevel@tonic-gate 	}
353*7c478bd9Sstevel@tonic-gate #ifdef pdp11
354*7c478bd9Sstevel@tonic-gate 	else
355*7c478bd9Sstevel@tonic-gate 		*execargs = (char *)dolv;	/* for `ps' cmd */
356*7c478bd9Sstevel@tonic-gate #endif
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	exfile(0);
360*7c478bd9Sstevel@tonic-gate 	done(0);
361*7c478bd9Sstevel@tonic-gate }
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate static int
364*7c478bd9Sstevel@tonic-gate exfile(prof)
365*7c478bd9Sstevel@tonic-gate BOOL	prof;
366*7c478bd9Sstevel@tonic-gate {
367*7c478bd9Sstevel@tonic-gate 	time_t	mailtime = 0;	/* Must not be a register variable */
368*7c478bd9Sstevel@tonic-gate 	time_t 	curtime = 0;
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	/*
371*7c478bd9Sstevel@tonic-gate 	 * move input
372*7c478bd9Sstevel@tonic-gate 	 */
373*7c478bd9Sstevel@tonic-gate 	if (input > 0)
374*7c478bd9Sstevel@tonic-gate 	{
375*7c478bd9Sstevel@tonic-gate 		Ldup(input, INIO);
376*7c478bd9Sstevel@tonic-gate 		input = INIO;
377*7c478bd9Sstevel@tonic-gate 	}
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	setmode(prof);
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	if (setjmp(errshell) && prof)
383*7c478bd9Sstevel@tonic-gate 	{
384*7c478bd9Sstevel@tonic-gate 		close(input);
385*7c478bd9Sstevel@tonic-gate 		(void) endjobs(0);
386*7c478bd9Sstevel@tonic-gate 		return;
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 	/*
389*7c478bd9Sstevel@tonic-gate 	 * error return here
390*7c478bd9Sstevel@tonic-gate 	 */
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	loopcnt = peekc = peekn = 0;
393*7c478bd9Sstevel@tonic-gate 	fndef = 0;
394*7c478bd9Sstevel@tonic-gate 	nohash = 0;
395*7c478bd9Sstevel@tonic-gate 	iopend = 0;
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	if (input >= 0)
398*7c478bd9Sstevel@tonic-gate 		initf(input);
399*7c478bd9Sstevel@tonic-gate 	/*
400*7c478bd9Sstevel@tonic-gate 	 * command loop
401*7c478bd9Sstevel@tonic-gate 	 */
402*7c478bd9Sstevel@tonic-gate 	for (;;)
403*7c478bd9Sstevel@tonic-gate 	{
404*7c478bd9Sstevel@tonic-gate 		tdystak(0);
405*7c478bd9Sstevel@tonic-gate 		stakchk();	/* may reduce sbrk */
406*7c478bd9Sstevel@tonic-gate 		exitset();
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 		if ((flags & prompt) && standin->fstak == 0 && !eof)
409*7c478bd9Sstevel@tonic-gate 		{
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 			if (mailp)
412*7c478bd9Sstevel@tonic-gate 			{
413*7c478bd9Sstevel@tonic-gate 				time(&curtime);
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 				if ((curtime - mailtime) >= mailchk)
416*7c478bd9Sstevel@tonic-gate 				{
417*7c478bd9Sstevel@tonic-gate 					chkmail();
418*7c478bd9Sstevel@tonic-gate 					mailtime = curtime;
419*7c478bd9Sstevel@tonic-gate 				}
420*7c478bd9Sstevel@tonic-gate 			}
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 			/* necessary to print jobs in a timely manner */
423*7c478bd9Sstevel@tonic-gate 			if (trapnote & TRAPSET)
424*7c478bd9Sstevel@tonic-gate 				chktrap();
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 			prs(ps1nod.namval);
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate #ifdef TIME_OUT
429*7c478bd9Sstevel@tonic-gate 			alarm(TIMEOUT);
430*7c478bd9Sstevel@tonic-gate #endif
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 		}
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 		trapnote = 0;
435*7c478bd9Sstevel@tonic-gate 		peekc = readwc();
436*7c478bd9Sstevel@tonic-gate 		if (eof) {
437*7c478bd9Sstevel@tonic-gate 			if (endjobs(JOB_STOPPED))
438*7c478bd9Sstevel@tonic-gate 				return;
439*7c478bd9Sstevel@tonic-gate 			eof = 0;
440*7c478bd9Sstevel@tonic-gate 		}
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate #ifdef TIME_OUT
443*7c478bd9Sstevel@tonic-gate 		alarm(0);
444*7c478bd9Sstevel@tonic-gate #endif
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 		{
447*7c478bd9Sstevel@tonic-gate 			register struct trenod *t;
448*7c478bd9Sstevel@tonic-gate 			t = cmd(NL, MTFLG);
449*7c478bd9Sstevel@tonic-gate 			if (t == NULL && flags & ttyflg)
450*7c478bd9Sstevel@tonic-gate 				freejobs();
451*7c478bd9Sstevel@tonic-gate 			else
452*7c478bd9Sstevel@tonic-gate 				execute(t, 0, eflag);
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 		eof |= (flags & oneflg);
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	}
458*7c478bd9Sstevel@tonic-gate }
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate chkpr()
461*7c478bd9Sstevel@tonic-gate {
462*7c478bd9Sstevel@tonic-gate 	if ((flags & prompt) && standin->fstak == 0)
463*7c478bd9Sstevel@tonic-gate 		prs(ps2nod.namval);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate settmp()
467*7c478bd9Sstevel@tonic-gate {
468*7c478bd9Sstevel@tonic-gate 	int i;
469*7c478bd9Sstevel@tonic-gate 	i = ltos(mypid);
470*7c478bd9Sstevel@tonic-gate 	serial = 0;
471*7c478bd9Sstevel@tonic-gate 	tmpname = movstr(numbuf + i, &tmpout[TMPNAM]);
472*7c478bd9Sstevel@tonic-gate }
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate Ldup(fa, fb)
475*7c478bd9Sstevel@tonic-gate register int	fa, fb;
476*7c478bd9Sstevel@tonic-gate {
477*7c478bd9Sstevel@tonic-gate #ifdef RES
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	dup(fa | DUPFLG, fb);
480*7c478bd9Sstevel@tonic-gate 	close(fa);
481*7c478bd9Sstevel@tonic-gate 	ioctl(fb, FIOCLEX, 0);
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate #else
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (fa >= 0) {
486*7c478bd9Sstevel@tonic-gate 		if (fa != fb)
487*7c478bd9Sstevel@tonic-gate 		{
488*7c478bd9Sstevel@tonic-gate 			close(fb);
489*7c478bd9Sstevel@tonic-gate 			fcntl(fa, 0, fb); /* normal dup */
490*7c478bd9Sstevel@tonic-gate 			close(fa);
491*7c478bd9Sstevel@tonic-gate 		}
492*7c478bd9Sstevel@tonic-gate 		fcntl(fb, 2, 1);	/* autoclose for fb */
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate #endif
496*7c478bd9Sstevel@tonic-gate }
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate chkmail()
500*7c478bd9Sstevel@tonic-gate {
501*7c478bd9Sstevel@tonic-gate 	register unsigned char 	*s = mailp;
502*7c478bd9Sstevel@tonic-gate 	register unsigned char	*save;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	long	*ptr = mod_time;
505*7c478bd9Sstevel@tonic-gate 	unsigned char	*start;
506*7c478bd9Sstevel@tonic-gate 	BOOL	flg;
507*7c478bd9Sstevel@tonic-gate 	struct stat	statb;
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	while (*s) {
510*7c478bd9Sstevel@tonic-gate 		start = s;
511*7c478bd9Sstevel@tonic-gate 		save = 0;
512*7c478bd9Sstevel@tonic-gate 		flg = 0;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 		while (*s) {
515*7c478bd9Sstevel@tonic-gate 			if (*s != COLON) {
516*7c478bd9Sstevel@tonic-gate 				if (*s == '%' && save == 0)
517*7c478bd9Sstevel@tonic-gate 					save = s;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 				s++;
520*7c478bd9Sstevel@tonic-gate 			} else {
521*7c478bd9Sstevel@tonic-gate 				flg = 1;
522*7c478bd9Sstevel@tonic-gate 				*s = 0;
523*7c478bd9Sstevel@tonic-gate 			}
524*7c478bd9Sstevel@tonic-gate 		}
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 		if (save)
527*7c478bd9Sstevel@tonic-gate 			*save = 0;
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 		if (*start && stat((const char *)start, &statb) >= 0) {
530*7c478bd9Sstevel@tonic-gate 			if (statb.st_size && *ptr &&
531*7c478bd9Sstevel@tonic-gate 			    statb.st_mtime != *ptr) {
532*7c478bd9Sstevel@tonic-gate 				if (save) {
533*7c478bd9Sstevel@tonic-gate 					prs(save+1);
534*7c478bd9Sstevel@tonic-gate 					newline();
535*7c478bd9Sstevel@tonic-gate 				}
536*7c478bd9Sstevel@tonic-gate 				else
537*7c478bd9Sstevel@tonic-gate 					prs(mailmsg);
538*7c478bd9Sstevel@tonic-gate 			}
539*7c478bd9Sstevel@tonic-gate 			*ptr = statb.st_mtime;
540*7c478bd9Sstevel@tonic-gate 		} else if (*ptr == 0)
541*7c478bd9Sstevel@tonic-gate 			*ptr = 1;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 		if (save)
544*7c478bd9Sstevel@tonic-gate 			*save = '%';
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 		if (flg)
547*7c478bd9Sstevel@tonic-gate 			*s++ = COLON;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 		ptr++;
550*7c478bd9Sstevel@tonic-gate 	}
551*7c478bd9Sstevel@tonic-gate }
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate setmail(mailpath)
555*7c478bd9Sstevel@tonic-gate 	unsigned char *mailpath;
556*7c478bd9Sstevel@tonic-gate {
557*7c478bd9Sstevel@tonic-gate 	register unsigned char	*s = mailpath;
558*7c478bd9Sstevel@tonic-gate 	register int 	cnt = 1;
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	long	*ptr;
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 	free(mod_time);
563*7c478bd9Sstevel@tonic-gate 	if (mailp = mailpath)
564*7c478bd9Sstevel@tonic-gate 	{
565*7c478bd9Sstevel@tonic-gate 		while (*s)
566*7c478bd9Sstevel@tonic-gate 		{
567*7c478bd9Sstevel@tonic-gate 			if (*s == COLON)
568*7c478bd9Sstevel@tonic-gate 				cnt += 1;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 			s++;
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 		ptr = mod_time = (long *)alloc(sizeof (long) * cnt);
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 		while (cnt)
576*7c478bd9Sstevel@tonic-gate 		{
577*7c478bd9Sstevel@tonic-gate 			*ptr = 0;
578*7c478bd9Sstevel@tonic-gate 			ptr++;
579*7c478bd9Sstevel@tonic-gate 			cnt--;
580*7c478bd9Sstevel@tonic-gate 		}
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate }
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate void
585*7c478bd9Sstevel@tonic-gate setwidth()
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	unsigned char *name = lookup("LC_CTYPE")->namval;
588*7c478bd9Sstevel@tonic-gate 	if (!name || !*name)
589*7c478bd9Sstevel@tonic-gate 		name = lookup("LANG")->namval;
590*7c478bd9Sstevel@tonic-gate 	/*
591*7c478bd9Sstevel@tonic-gate 	 * Do locale processing only if /usr is mounted.
592*7c478bd9Sstevel@tonic-gate 	 */
593*7c478bd9Sstevel@tonic-gate 	if (localedir_exists) {
594*7c478bd9Sstevel@tonic-gate 		if (!name || !*name)
595*7c478bd9Sstevel@tonic-gate 			(void) setlocale(LC_CTYPE, "C");
596*7c478bd9Sstevel@tonic-gate 		else
597*7c478bd9Sstevel@tonic-gate 			(void) setlocale(LC_CTYPE, (const char *)name);
598*7c478bd9Sstevel@tonic-gate 	}
599*7c478bd9Sstevel@tonic-gate }
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate setmode(prof)
602*7c478bd9Sstevel@tonic-gate {
603*7c478bd9Sstevel@tonic-gate 	/*
604*7c478bd9Sstevel@tonic-gate 	 * decide whether interactive
605*7c478bd9Sstevel@tonic-gate 	 */
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	if ((flags & intflg) ||
608*7c478bd9Sstevel@tonic-gate 	    ((flags&oneflg) == 0 &&
609*7c478bd9Sstevel@tonic-gate 	    isatty(output) &&
610*7c478bd9Sstevel@tonic-gate 	    isatty(input)))
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	{
613*7c478bd9Sstevel@tonic-gate 		dfault(&ps1nod, (geteuid() ? stdprompt : supprompt));
614*7c478bd9Sstevel@tonic-gate 		dfault(&ps2nod, readmsg);
615*7c478bd9Sstevel@tonic-gate 		flags |= ttyflg | prompt;
616*7c478bd9Sstevel@tonic-gate 		if (mailpnod.namflg != N_DEFAULT)
617*7c478bd9Sstevel@tonic-gate 			setmail(mailpnod.namval);
618*7c478bd9Sstevel@tonic-gate 		else
619*7c478bd9Sstevel@tonic-gate 			setmail(mailnod.namval);
620*7c478bd9Sstevel@tonic-gate 		startjobs();
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 	else
623*7c478bd9Sstevel@tonic-gate 	{
624*7c478bd9Sstevel@tonic-gate 		flags |= prof;
625*7c478bd9Sstevel@tonic-gate 		flags &= ~prompt;
626*7c478bd9Sstevel@tonic-gate 	}
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate /*
630*7c478bd9Sstevel@tonic-gate  * A generic call back routine to output error messages from the
631*7c478bd9Sstevel@tonic-gate  * policy backing functions called by pfsh.
632*7c478bd9Sstevel@tonic-gate  *
633*7c478bd9Sstevel@tonic-gate  * msg must contain '\n' if a new line is to be printed.
634*7c478bd9Sstevel@tonic-gate  */
635*7c478bd9Sstevel@tonic-gate void
636*7c478bd9Sstevel@tonic-gate secpolicy_print(int level, const char *msg)
637*7c478bd9Sstevel@tonic-gate {
638*7c478bd9Sstevel@tonic-gate 	switch (level) {
639*7c478bd9Sstevel@tonic-gate 	case SECPOLICY_WARN:
640*7c478bd9Sstevel@tonic-gate 	default:
641*7c478bd9Sstevel@tonic-gate 		prs(msg);	/* prs() does gettext() */
642*7c478bd9Sstevel@tonic-gate 		return;
643*7c478bd9Sstevel@tonic-gate 	case SECPOLICY_ERROR:
644*7c478bd9Sstevel@tonic-gate 		error(msg);
645*7c478bd9Sstevel@tonic-gate 		break;
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate }
648