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