xref: /csrg-svn/local/toolchest/ksh/sh/main.c (revision 35151)
1*35151Smarc /*
2*35151Smarc 
3*35151Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35151Smarc  *      All Rights Reserved
5*35151Smarc 
6*35151Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35151Smarc  *      CODE OF AT&T.
8*35151Smarc  *      The copyright notice above does not
9*35151Smarc  *      evidence any actual or intended
10*35151Smarc  *      publication of such source code.
11*35151Smarc 
12*35151Smarc  */
13*35151Smarc /* @(#)main.c	1.1 */
14*35151Smarc /*
15*35151Smarc  * UNIX shell
16*35151Smarc  *
17*35151Smarc  * S. R. Bourne
18*35151Smarc  * Rewritten by David Korn
19*35151Smarc  * AT&T Bell Laboratories
20*35151Smarc  *
21*35151Smarc  */
22*35151Smarc 
23*35151Smarc #ifdef BSD
24*35151Smarc # ifdef BSD_4_2
25*35151Smarc # include	<sys/param.h>
26*35151Smarc # else
27*35151Smarc # include	<sys/types.h>
28*35151Smarc # endif /* BSD_4_2 */
29*35151Smarc #include   	 <sgtty.h>
30*35151Smarc #else
31*35151Smarc #include	<sys/types.h>
32*35151Smarc #endif /* BSD */
33*35151Smarc #include	<sys/stat.h>
34*35151Smarc #include	"defs.h"
35*35151Smarc #include	"sym.h"
36*35151Smarc #include	"flags.h"
37*35151Smarc #include	"io.h"
38*35151Smarc #include	"history.h"
39*35151Smarc #include	"mode.h"
40*35151Smarc #include	"name.h"
41*35151Smarc #include	"stak.h"
42*35151Smarc #include	"timeout.h"
43*35151Smarc #include	"brkincr.h"
44*35151Smarc #include	"builtins.h"
45*35151Smarc #ifdef pdp11
46*35151Smarc #include	<execargs.h>
47*35151Smarc #endif	/* pdp11 */
48*35151Smarc 
49*35151Smarc #define FC_CHAR		'!'
50*35151Smarc 
51*35151Smarc 
52*35151Smarc /* These routines are defined by this module */
53*35151Smarc int	main();
54*35151Smarc void	chkpr();
55*35151Smarc char	*getpwd();
56*35151Smarc 
57*35151Smarc /* These routines are referenced by this module */
58*35151Smarc extern void	addblok();
59*35151Smarc extern void	assign();
60*35151Smarc extern FILE	*chkopen();
61*35151Smarc extern TREPTR	cmd();
62*35151Smarc extern void	done();
63*35151Smarc extern void	fassign();
64*35151Smarc extern char	*getpwd();
65*35151Smarc extern void	gscan_some();
66*35151Smarc extern int	hist_open();
67*35151Smarc extern void	hist_close();
68*35151Smarc extern void	hist_eof();
69*35151Smarc extern void	hist_flush();
70*35151Smarc extern void	initf();
71*35151Smarc extern char	*itos();
72*35151Smarc extern char	*mactry();
73*35151Smarc extern char	*movstr();
74*35151Smarc extern void	mem_reinit();
75*35151Smarc extern void	meminit();
76*35151Smarc extern FILE	*pathopen();
77*35151Smarc extern void	p_flush();
78*35151Smarc extern void	p_num();
79*35151Smarc extern void	p_str();
80*35151Smarc extern void	p_setout();
81*35151Smarc extern void	rmlocal();
82*35151Smarc extern char	*strrchr();
83*35151Smarc extern void	settemp();
84*35151Smarc extern char	*simple();
85*35151Smarc extern void	stdsigs();
86*35151Smarc extern void	tdystak();
87*35151Smarc extern char	*valup();
88*35151Smarc 
89*35151Smarc static void exfile();
90*35151Smarc static void pr_prompt();
91*35151Smarc static void chkmail();
92*35151Smarc 
93*35151Smarc extern char **environ;
94*35151Smarc 
95*35151Smarc 
96*35151Smarc /* The following is defined for fixcmd */
97*35151Smarc 
98*35151Smarc static struct stat lastmail;
99*35151Smarc static long mailtime;
100*35151Smarc static BOOL	beenhere = 0;
101*35151Smarc static int euserid;
102*35151Smarc static int egroupid;
103*35151Smarc 
main(c,v)104*35151Smarc main(c, v)
105*35151Smarc int 	c;
106*35151Smarc register char *v[];
107*35151Smarc {
108*35151Smarc 	FILE fd;
109*35151Smarc 	register char *sim;
110*35151Smarc 	register int 	rsflag=1;	/* local restricted flag */
111*35151Smarc #ifdef apollo
112*35151Smarc 	extern char pm_$unix_env ;
113*35151Smarc 	extern FILE *_iobmax;
114*35151Smarc 	pm_$unix_env = -1;
115*35151Smarc 	_iobmax = _iob + 20;
116*35151Smarc #endif	/* apollo */
117*35151Smarc 	standout = stdout;
118*35151Smarc 	p_setout(stderr);
119*35151Smarc 	standin = &stdfile;
120*35151Smarc 	userid=getuid();
121*35151Smarc 	euserid=geteuid();
122*35151Smarc 	egroupid=getegid();
123*35151Smarc 	time(&mailtime);
124*35151Smarc 	stdsigs();
125*35151Smarc 	/* initialize storage allocation */
126*35151Smarc 	stakbot = 0;
127*35151Smarc 	addblok((unsigned)0);
128*35151Smarc 	/* set up memory for namenods */
129*35151Smarc 	meminit();
130*35151Smarc 	/* set names from userenv
131*35151Smarc 	 *  'rsflag' is zero if SHELL variable is
132*35151Smarc 	 * set in environment and contains an'r' in
133*35151Smarc 	 * the simple file part of the value.
134*35151Smarc 	 */
135*35151Smarc 
136*35151Smarc 	rsflag=genenv();
137*35151Smarc 	/* a shell is also restricted if argv(0) has
138*35151Smarc 	 *  an 'rsh' for its simple name
139*35151Smarc 	 */
140*35151Smarc 	sim = simple(*v);
141*35151Smarc 	if(*sim=='-')
142*35151Smarc 	{
143*35151Smarc 		sim++;
144*35151Smarc 		login_sh = 2;
145*35151Smarc 	}
146*35151Smarc 	/* check for restricted shell */
147*35151Smarc 	if(c>0 && gmatch(sim,"*rsh"))
148*35151Smarc 		rsflag=0;
149*35151Smarc 	/* look for options */
150*35151Smarc 	/* dolc is $#	*/
151*35151Smarc 	dolc=arg_opts(c,v);
152*35151Smarc 	dolv=v+c-dolc--;
153*35151Smarc 	dolv[0] = v[0];
154*35151Smarc 	if(dolc < 1)
155*35151Smarc 		on_option(STDFLG);
156*35151Smarc 	if(is_option(STDFLG|CFLAG)==0)
157*35151Smarc 	{
158*35151Smarc 		dolc--;
159*35151Smarc 		dolv++;
160*35151Smarc 	}
161*35151Smarc 	/* set[ug]id scripts run with the -p flag */
162*35151Smarc 	if(userid!=euserid || getgid()!=egroupid)
163*35151Smarc 	{
164*35151Smarc #ifdef BSD_4_2
165*35151Smarc 		/* careful of #! setuid scripts with name beginning with - */
166*35151Smarc 		if(login_sh && strcmp(v[0],v[1])==0)
167*35151Smarc 			error(prohibited);
168*35151Smarc #endif /* BSD_4_2 */
169*35151Smarc 		assign(PATHNOD,defpath);
170*35151Smarc 		on_option(PRIVM);
171*35151Smarc 	}
172*35151Smarc 	if(is_option(RSHFLG))
173*35151Smarc 	{
174*35151Smarc 		rsflag = 0;
175*35151Smarc 		off_option(RSHFLG);
176*35151Smarc 	}
177*35151Smarc 	/*
178*35151Smarc 	 * return here for shell file execution
179*35151Smarc 	 * but not for parenthesis subshells
180*35151Smarc 	 */
181*35151Smarc 	setjmp(subshell);
182*35151Smarc 	cmdadr=dolv[0]; /* cmdadr is $0 */
183*35151Smarc 	/* set pidname '$$' */
184*35151Smarc 	movstr(itos(ppid=getpid()),pidadr);
185*35151Smarc 	srand(ppid);
186*35151Smarc 	ppid = getppid();
187*35151Smarc 	settemp(pidadr);
188*35151Smarc 	if((beenhere++)==0)
189*35151Smarc 	{
190*35151Smarc 		int prof = !is_option(PRIVM);
191*35151Smarc 		/* decide whether shell is interactive */
192*35151Smarc 		if(is_option(ONEFLG|CFLAG)==0 && is_option(STDFLG) && isatty(0) &&
193*35151Smarc 				isatty(2))
194*35151Smarc 			on_option(INTFLG);
195*35151Smarc 		if(ppid==1)
196*35151Smarc 			login_sh++;
197*35151Smarc 		if(login_sh >= 2)
198*35151Smarc 		{
199*35151Smarc 			/* ? profile */
200*35151Smarc 			login_sh += 2;
201*35151Smarc #ifdef JOBS
202*35151Smarc # ifdef BSD
203*35151Smarc 			init_jobs(1);
204*35151Smarc # endif	/* BSD */
205*35151Smarc # ifdef SXT
206*35151Smarc 			init_jobs(1);
207*35151Smarc # endif /* SXT */
208*35151Smarc #endif	/* JOBS */
209*35151Smarc 			/*	system profile	*/
210*35151Smarc 			if((input=pathopen(sysprofile)) != NULL)
211*35151Smarc 				{
212*35151Smarc 					exfile(TTYFLG);	/* file exists */
213*35151Smarc 					fclose(input);
214*35151Smarc 				}
215*35151Smarc 			if(prof &&  (input=pathopen(mactry(profile))) != NULL)
216*35151Smarc 			{
217*35151Smarc 				exfile(TTYFLG);
218*35151Smarc 				states &= ~TTYFLG;
219*35151Smarc 				fclose(input);
220*35151Smarc 			}
221*35151Smarc 		}
222*35151Smarc 		/* make sure PWD is set up correctly */
223*35151Smarc 		if(getpwd(1))
224*35151Smarc 			attrib(PWDNOD,N_EXPORT);
225*35151Smarc 		if(prof)
226*35151Smarc 		{
227*35151Smarc 			if(sim = valup(ENVNOD))
228*35151Smarc 				if(*(sim = mactry(sim)) == 0)
229*35151Smarc 					sim = 0;
230*35151Smarc 		}
231*35151Smarc 		else
232*35151Smarc 			sim = suid_profile;
233*35151Smarc 		if(sim && (input = pathopen(sim)) != NULL)
234*35151Smarc 		{
235*35151Smarc 			exfile(TTYFLG);
236*35151Smarc 			states &= ~TTYFLG;
237*35151Smarc 			fclose(input);
238*35151Smarc 		}
239*35151Smarc 		if(rsflag==0)
240*35151Smarc 			on_option(RSHFLG);
241*35151Smarc 		/* open input file if specified */
242*35151Smarc 		if(comdiv)
243*35151Smarc 		{
244*35151Smarc 			estabf(comdiv,&fd);
245*35151Smarc 		}
246*35151Smarc 		else
247*35151Smarc 		{
248*35151Smarc 			sim = cmdadr;
249*35151Smarc 			cmdadr = v[0];
250*35151Smarc 			if(is_option(STDFLG))
251*35151Smarc 				input = stdin;
252*35151Smarc 			else
253*35151Smarc 			{
254*35151Smarc #ifdef VFORK
255*35151Smarc 				char *sp = sim;
256*35151Smarc 				/* avoid path search if we already have the
257*35151Smarc 				 * path name in the environment
258*35151Smarc 				 */
259*35151Smarc 				if(strcmp(sim,simple(*environ))==0)
260*35151Smarc 					sp = (*environ)+2;
261*35151Smarc #endif /* VFORK */
262*35151Smarc #ifdef SUID_EXEC
263*35151Smarc 				/* open stream should have been passed into shell */
264*35151Smarc 				if(gmatch(sim,devfdNN))
265*35151Smarc 				{
266*35151Smarc 					struct stat statb;
267*35151Smarc 					int fd = atoi(sim+8);
268*35151Smarc 					if(fstat(fd,&statb)<0)
269*35151Smarc 						failed(cmdadr,badopen);
270*35151Smarc 					input = fdopen(fd,"r");
271*35151Smarc 					sim = cmdadr;
272*35151Smarc 					off_option(EXECPR|READPR);
273*35151Smarc 				}
274*35151Smarc 				else
275*35151Smarc #endif /* SUID_EXEC */
276*35151Smarc #ifdef VFORK
277*35151Smarc 				if((input=pathopen(sp))==NULL)
278*35151Smarc #else
279*35151Smarc 				if((input=pathopen(sim))==NULL)
280*35151Smarc 					/* for compatibility with bsh */
281*35151Smarc 					if((input=chkopen(sim))==NULL)
282*35151Smarc #endif /* VFORK */
283*35151Smarc 						failed(sim,badopen);
284*35151Smarc 				/* eliminate local aliases and functions */
285*35151Smarc 				gscan_some(rmlocal,alias,N_EXPORT,0);
286*35151Smarc 				gscan_some(rmlocal,prnames,N_EXPORT,0);
287*35151Smarc 			}
288*35151Smarc 			cmdadr = sim;
289*35151Smarc 			comdiv--;
290*35151Smarc #ifdef ACCT
291*35151Smarc 			initacct();
292*35151Smarc 			if(fileno(input) != 0)
293*35151Smarc 				preacct(cmdadr);
294*35151Smarc #endif	/* ACCT */
295*35151Smarc 		}
296*35151Smarc 	}
297*35151Smarc #ifdef pdp11
298*35151Smarc 	else
299*35151Smarc 		*execargs=(char *) dolv;	/* for `ps' cmd */
300*35151Smarc #endif	/* pdp11 */
301*35151Smarc 	states |= is_option(INTFLG);
302*35151Smarc 	exfile(0);
303*35151Smarc 	if(states&PROMPT)
304*35151Smarc 	        newline();
305*35151Smarc 	done(0);
306*35151Smarc }
307*35151Smarc 
exfile(prof)308*35151Smarc static void	exfile(prof)
309*35151Smarc register int prof;
310*35151Smarc {
311*35151Smarc 	long curtime;
312*35151Smarc 	TREPTR t;
313*35151Smarc 	register FILE *fp = input;
314*35151Smarc 	register struct fixcmd *fixp;
315*35151Smarc 	register int fno;
316*35151Smarc 	unsigned execflags;
317*35151Smarc 	/* move input */
318*35151Smarc 	if(fisopen(fp) && (fno=fileno(fp))!=F_STRING)
319*35151Smarc 	{
320*35151Smarc 		if(fno > 0)
321*35151Smarc 		{
322*35151Smarc 			fp = input = frenumber(fp,INIO);
323*35151Smarc 			setbuf(fp,(char*)_sibuf);
324*35151Smarc 			if(prof==0)
325*35151Smarc 				setbuf(stdin,NIL);
326*35151Smarc 		}
327*35151Smarc 		/* if stdin is a pipe it must be unbuffered */
328*35151Smarc 		else
329*35151Smarc 			setbuf(fp,ispipe(fp)?NIL:(char*)_sibuf);
330*35151Smarc 	}
331*35151Smarc 	if(states&INTFLG)
332*35151Smarc 	{
333*35151Smarc 		if(isnull(PS1NOD))
334*35151Smarc 			assign(PS1NOD, (euserid?stdprompt:supprompt));
335*35151Smarc 		states |= TTYFLG|PROMPT;
336*35151Smarc 		ignsig(SIGTERM);
337*35151Smarc 		hist_open();
338*35151Smarc 		if(fc_fix)
339*35151Smarc 			on_option(FIXFLG);
340*35151Smarc #ifdef JOBS
341*35151Smarc # ifdef BSD
342*35151Smarc 		if(login_sh<=1)
343*35151Smarc 			init_jobs(0);
344*35151Smarc # endif	/* BSD */
345*35151Smarc # ifdef SXT
346*35151Smarc 		if(login_sh<=1)
347*35151Smarc 			init_jobs(0);
348*35151Smarc # endif /* SXT */
349*35151Smarc #endif	/* JOBS */
350*35151Smarc 	}
351*35151Smarc 	else
352*35151Smarc 	{
353*35151Smarc 		if(prof)
354*35151Smarc 			states |= prof;
355*35151Smarc 		else
356*35151Smarc 		{
357*35151Smarc 			off_option(EDITVI|EMACS|GMACS);
358*35151Smarc 			on_option(HASHALL|INPROC);
359*35151Smarc 		}
360*35151Smarc 		states &= ~(PROMPT|MONITOR);
361*35151Smarc 		off_option(FIXFLG);
362*35151Smarc 	}
363*35151Smarc 	fixp = fc_fix;
364*35151Smarc 	if(setjmp(errshell) && prof)
365*35151Smarc 	{
366*35151Smarc 		fclose(fp);
367*35151Smarc 		return;
368*35151Smarc 	}
369*35151Smarc 	/* error return here */
370*35151Smarc 	freturn = (jmp_buf*)errshell;
371*35151Smarc 	loopcnt=peekc=peekn=0;
372*35151Smarc 	iopend=0;
373*35151Smarc 	linked = 0;
374*35151Smarc 	if(fp!=NULL)
375*35151Smarc 		initf(fp);
376*35151Smarc 	if(feof(fp))
377*35151Smarc 		goto eof_or_error;
378*35151Smarc 	/* command loop */
379*35151Smarc 	while(1)
380*35151Smarc 	{
381*35151Smarc 		tdystak((STKPTR)0);
382*35151Smarc 		stakchk(); /* may reduce sbrk */
383*35151Smarc 		exitset();
384*35151Smarc 		states &= ~(ERRFLG|READPR|RWAIT|MONITOR);
385*35151Smarc 		states |= is_option(READPR)|WAITING|ERRFLG;
386*35151Smarc 		/* -eim  flags don't apply to profiles */
387*35151Smarc 		if(prof)
388*35151Smarc 			states &= ~(INTFLG|ERRFLG|MONITOR);
389*35151Smarc 		p_setout(stderr);
390*35151Smarc 		if((states&PROMPT) && standin->fstak==0 && !feof(fp))
391*35151Smarc 		{
392*35151Smarc 			register char *mail;
393*35151Smarc #ifdef JOBS
394*35151Smarc 			/* allow children to be stopped*/
395*35151Smarc 			states &= ~(MONITOR|NONSTOP);
396*35151Smarc 			states |= is_option(MONITOR);
397*35151Smarc 			list_jobs(N_FLAG);
398*35151Smarc #endif	/* JOBS */
399*35151Smarc 			if((mail=valup(MAILPNOD)) || (mail=valup(MAILNOD)))
400*35151Smarc 			{
401*35151Smarc 				time(&curtime);
402*35151Smarc 				if ((curtime - mailtime) >= mailchk)
403*35151Smarc 				{
404*35151Smarc 					chkmail(mail);
405*35151Smarc 					mailtime = curtime;
406*35151Smarc 				}
407*35151Smarc 			}
408*35151Smarc 			if(fixp)
409*35151Smarc 				hist_eof();
410*35151Smarc 			pr_prompt(mactry(valup(PS1NOD)));
411*35151Smarc 			/* sets timeout for command entry */
412*35151Smarc #if TIMEOUT!=0
413*35151Smarc 			if(timeout <= 0 || timeout > TIMEOUT)
414*35151Smarc 				timeout = TIMEOUT;
415*35151Smarc #endif
416*35151Smarc 			if(timeout>0)
417*35151Smarc 				alarm((unsigned)timeout);
418*35151Smarc 			standin->flin = 1;
419*35151Smarc 		}
420*35151Smarc 		trapnote=0;
421*35151Smarc 		peekc=readc();
422*35151Smarc 		if(feof(fp) || ferror(fp))
423*35151Smarc 		{
424*35151Smarc 		eof_or_error:
425*35151Smarc 			if((states&PROMPT) && standin->fstak==0 && ferror(fp)==0)
426*35151Smarc 			{
427*35151Smarc 				clearerr(fp);
428*35151Smarc 				if(is_option(NOEOF) && !ferror(output))
429*35151Smarc 				{
430*35151Smarc 					p_str(logout,NL);
431*35151Smarc 					continue;
432*35151Smarc 				}
433*35151Smarc #ifdef JOBS
434*35151Smarc 				else if(close_jobs()<0)
435*35151Smarc 					continue;
436*35151Smarc #endif	/* JOBS */
437*35151Smarc 				hist_close();
438*35151Smarc 			}
439*35151Smarc 			return;
440*35151Smarc 		}
441*35151Smarc 		if(timeout>0)
442*35151Smarc 			alarm(0);
443*35151Smarc 		if((states&PROMPT) && fixp)
444*35151Smarc 		{
445*35151Smarc 			hist_eof();
446*35151Smarc 			putc(peekc,fixp->fixfd);
447*35151Smarc 		}
448*35151Smarc 		states |= is_option(FIXFLG);
449*35151Smarc 		states &= ~ WAITING;
450*35151Smarc 		t = cmd(NL,MTFLG);
451*35151Smarc 		if(fixp)
452*35151Smarc 			hist_flush();
453*35151Smarc 		if(t)
454*35151Smarc 		{
455*35151Smarc 			execflags = ERRFLG;
456*35151Smarc 			/* sh -c simple-command may not have to fork */
457*35151Smarc 			if(prof==0 && is_option(CFLAG) && (t->tretyp&COMMSK)==TCOM
458*35151Smarc 				&& nextchar(fp)==0)
459*35151Smarc 			{
460*35151Smarc 				execflags |= 1;
461*35151Smarc 			}
462*35151Smarc 			execute(t,execflags);
463*35151Smarc 		}
464*35151Smarc 	}
465*35151Smarc }
466*35151Smarc 
467*35151Smarc /*
468*35151Smarc  * if there is pending input, the prompt is not printed.
469*35151Smarc  * prints PS2 if flag is zero otherwise PS3
470*35151Smarc  */
471*35151Smarc 
chkpr(flag)472*35151Smarc void	chkpr(flag)
473*35151Smarc register int flag;
474*35151Smarc {
475*35151Smarc 	if(flag || (states&PROMPT) && standin->fstak==0)
476*35151Smarc 	{
477*35151Smarc 		/* if characters are in input buffer don't issue prompt */
478*35151Smarc 		if((flag?stdin:input)->_cnt > 0)
479*35151Smarc 			return;
480*35151Smarc 		p_setout(stderr);
481*35151Smarc 		fputs(valup(flag?PS3NOD:PS2NOD),output);
482*35151Smarc 	}
483*35151Smarc }
484*35151Smarc 
485*35151Smarc 
486*35151Smarc 
487*35151Smarc /* prints out messages if files in list have been modified since last call */
chkmail(files)488*35151Smarc static void chkmail(files)
489*35151Smarc char *files;
490*35151Smarc {
491*35151Smarc 	register char *cp,*sp,*qp;
492*35151Smarc 	register char save;
493*35151Smarc 	struct stat	statb;
494*35151Smarc 	if(*(cp=files) == 0)
495*35151Smarc 		return;
496*35151Smarc 	sp = cp;
497*35151Smarc 	do
498*35151Smarc 	{
499*35151Smarc 		/* skip to : or end of string saving first '?' */
500*35151Smarc 		for(qp=0;*sp && *sp != ':';sp++)
501*35151Smarc 			if((*sp == '?' || *sp=='%') && qp == 0)
502*35151Smarc 				qp = sp;
503*35151Smarc 		save = *sp;
504*35151Smarc 		*sp = 0;
505*35151Smarc 		/* change '?' to end-of-string */
506*35151Smarc 		if(qp)
507*35151Smarc 			*qp = 0;
508*35151Smarc 		gchain = NULL;
509*35151Smarc 		do
510*35151Smarc 		{
511*35151Smarc 			/* see if time has been modified since last checked
512*35151Smarc 			 * and the access time <= the modification time
513*35151Smarc 			 */
514*35151Smarc 			if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime
515*35151Smarc 				&& statb.st_atime <= statb.st_mtime)
516*35151Smarc 			{
517*35151Smarc 				/* check for directory */
518*35151Smarc 				if(gchain==NULL && (statb.st_mode&S_IFMT)==S_IFDIR)
519*35151Smarc 				{
520*35151Smarc 					/* generate list of directory entries */
521*35151Smarc 					f_complete(cp,"/*");
522*35151Smarc 				}
523*35151Smarc 				else
524*35151Smarc 				{
525*35151Smarc 					/*
526*35151Smarc 					 * If the file has shrunk,
527*35151Smarc 					 * or if the size is zero
528*35151Smarc 					 * then don't print anything
529*35151Smarc 					 */
530*35151Smarc 					if(statb.st_size &&
531*35151Smarc 						(  statb.st_ino != lastmail.st_ino
532*35151Smarc 						|| statb.st_dev != lastmail.st_dev
533*35151Smarc 						|| statb.st_size > lastmail.st_size))
534*35151Smarc 					{
535*35151Smarc 						/* save and restore $_ */
536*35151Smarc 						char *save = lastarg;
537*35151Smarc 						lastarg = cp;
538*35151Smarc 						p_str(mactry(qp==0?mailmsg:qp+1),NL);
539*35151Smarc 						lastarg = save;
540*35151Smarc 					}
541*35151Smarc 					lastmail = statb;
542*35151Smarc 					break;
543*35151Smarc 				}
544*35151Smarc 			}
545*35151Smarc 			if(gchain)
546*35151Smarc 			{
547*35151Smarc 				cp = gchain->argval;
548*35151Smarc 				gchain = gchain->argchn;
549*35151Smarc 			}
550*35151Smarc 			else
551*35151Smarc 				cp = NULL;
552*35151Smarc 		}
553*35151Smarc 		while(cp);
554*35151Smarc 		if(qp)
555*35151Smarc 			*qp = '?';
556*35151Smarc 		*sp++ = save;
557*35151Smarc 		cp = sp;
558*35151Smarc 	}
559*35151Smarc 	while(save);
560*35151Smarc 	tdystak((STKPTR)0);
561*35151Smarc }
562*35151Smarc 
563*35151Smarc /*
564*35151Smarc  * print the primary prompt
565*35151Smarc  */
566*35151Smarc 
pr_prompt(string)567*35151Smarc static void pr_prompt(string)
568*35151Smarc register char *string;
569*35151Smarc {
570*35151Smarc 	register char *cp;
571*35151Smarc 	register int c;
572*35151Smarc 	static short cmdno;
573*35151Smarc #ifdef BSD
574*35151Smarc 	int mode;
575*35151Smarc #include	<sys/ioctl.h>
576*35151Smarc 	mode = LFLUSHO;
577*35151Smarc 	ioctl(fileno(output),TIOCLBIC,&mode);
578*35151Smarc #endif	/* BSD */
579*35151Smarc 	p_flush();
580*35151Smarc 	p_setout(stderr);
581*35151Smarc 	for(cp=string;c= *cp;cp++)
582*35151Smarc 	{
583*35151Smarc 		if(c==FC_CHAR)
584*35151Smarc 		{
585*35151Smarc 			/* look at next character */
586*35151Smarc 			c = *++cp;
587*35151Smarc 			/* print out line number if not !! */
588*35151Smarc 			if(c!= FC_CHAR)
589*35151Smarc 				p_num(fc_fix?fc_fix->fixind:++cmdno,0);
590*35151Smarc 			if(c==0)
591*35151Smarc 				break;
592*35151Smarc 		}
593*35151Smarc 		putc(c,output);
594*35151Smarc 	}
595*35151Smarc #if VSH || ESH
596*35151Smarc 	*output->_ptr = 0;
597*35151Smarc 	/* prompt flushed later */
598*35151Smarc #else
599*35151Smarc 	p_flush();
600*35151Smarc #endif
601*35151Smarc }
602*35151Smarc 
603*35151Smarc /* make sure PWD is set up correctly */
604*35151Smarc 
605*35151Smarc /*
606*35151Smarc  * Return the value of the PWD variable
607*35151Smarc  * Invokes /bin/pwd if necessary
608*35151Smarc  * If mode non-zero, then PWD must have same device/inode as dot
609*35151Smarc  */
610*35151Smarc 
getpwd(mode)611*35151Smarc char *getpwd(mode)
612*35151Smarc {
613*35151Smarc 	register char *sim;
614*35151Smarc 	register int count = 0;
615*35151Smarc 	while((sim=valup(PWDNOD))==NULL || *sim==0 || (mode&&!eq_inode(sim,dot)))
616*35151Smarc 	{
617*35151Smarc 		if(count++ > 0)
618*35151Smarc 			return(NULL);
619*35151Smarc 		if((sim=valup(HOME)) && *sim=='/' && eq_inode(sim,dot))
620*35151Smarc 		{
621*35151Smarc 			fassign(PWDNOD,sim);
622*35151Smarc 			break;
623*35151Smarc 		}
624*35151Smarc 		else
625*35151Smarc 		{
626*35151Smarc #ifdef apollo
627*35151Smarc 			char buff[BUFSIZ+1];
628*35151Smarc 			extern char *getcwd();
629*35151Smarc 			sim=getcwd(buff+1,BUFSIZ);
630*35151Smarc 			if(buff[1]=='/' && buff[2]=='/')
631*35151Smarc 			{
632*35151Smarc 				buff[0]='/';
633*35151Smarc 				buff[1] = 'n';
634*35151Smarc 				sim = buff;
635*35151Smarc 			}
636*35151Smarc 			fassign(PWDNOD,sim);
637*35151Smarc #else
638*35151Smarc 			/* even restricted shells can pwd */
639*35151Smarc 			optflag savflags = flags;
640*35151Smarc 			off_option(RSHFLG);
641*35151Smarc 			execexp(setpwd,(FILE*)0);
642*35151Smarc 			flags = savflags;
643*35151Smarc #endif	/* apollo */
644*35151Smarc 		}
645*35151Smarc 	}
646*35151Smarc 	return(sim);
647*35151Smarc }
648*35151Smarc 
649*35151Smarc 
650*35151Smarc /*
651*35151Smarc  * This version of access checks against effective uid/gid
652*35151Smarc  */
653*35151Smarc 
access(name,mode)654*35151Smarc access(name, mode)
655*35151Smarc register char	*name;
656*35151Smarc register int mode;
657*35151Smarc {
658*35151Smarc 	struct stat statb;
659*35151Smarc 	if (stat(name, &statb) == 0)
660*35151Smarc 	{
661*35151Smarc 		if(mode == 0)
662*35151Smarc 			return(mode);
663*35151Smarc 		else if(euserid == 0)
664*35151Smarc 		{
665*35151Smarc 			if((statb.st_mode&S_IFMT) != S_IFREG || mode != 1)
666*35151Smarc 				return(0);
667*35151Smarc 		    	/* root needs execute permission for someone */
668*35151Smarc 			mode = (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
669*35151Smarc 		}
670*35151Smarc 		else if(euserid == statb.st_uid)
671*35151Smarc 			mode <<= 6;
672*35151Smarc 		else if(egroupid == statb.st_gid)
673*35151Smarc 			mode <<= 3;
674*35151Smarc #ifdef BSD
675*35151Smarc # ifdef BSD_4_2
676*35151Smarc 		/* in BSD_4_2 you can be in several groups */
677*35151Smarc 		else
678*35151Smarc 		{
679*35151Smarc 			int groups[NGROUPS];
680*35151Smarc 			register int n;
681*35151Smarc 			n = getgroups(NGROUPS,groups);
682*35151Smarc 			while(--n >= 0)
683*35151Smarc 			{
684*35151Smarc 				if(groups[n] == statb.st_gid)
685*35151Smarc 				{
686*35151Smarc 					mode <<= 3;
687*35151Smarc 					break;
688*35151Smarc 				}
689*35151Smarc 			}
690*35151Smarc 		}
691*35151Smarc # endif /* BSD_4_2 */
692*35151Smarc #endif /* BSD */
693*35151Smarc 		if(statb.st_mode & mode)
694*35151Smarc 			return(0);
695*35151Smarc 	}
696*35151Smarc 	return(-1);
697*35151Smarc }
698*35151Smarc 
699