1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1982-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * UNIX shell
23da2e3ebdSchin *
24da2e3ebdSchin * S. R. Bourne
25da2e3ebdSchin * Rewritten By David Korn
26da2e3ebdSchin * AT&T Labs
27da2e3ebdSchin *
28da2e3ebdSchin */
29*b30d1939SAndy Fiddaman /*
30*b30d1939SAndy Fiddaman * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
31*b30d1939SAndy Fiddaman */
32da2e3ebdSchin
33da2e3ebdSchin #include <ast.h>
34da2e3ebdSchin #include <sfio.h>
35da2e3ebdSchin #include <stak.h>
36da2e3ebdSchin #include <ls.h>
37da2e3ebdSchin #include <fcin.h>
38da2e3ebdSchin #include "defs.h"
39da2e3ebdSchin #include "variables.h"
40da2e3ebdSchin #include "path.h"
41da2e3ebdSchin #include "io.h"
42da2e3ebdSchin #include "jobs.h"
4334f9b3eeSRoland Mainz #include "shlex.h"
44da2e3ebdSchin #include "shnodes.h"
45da2e3ebdSchin #include "history.h"
46da2e3ebdSchin #include "timeout.h"
47da2e3ebdSchin #include "FEATURE/time"
48da2e3ebdSchin #include "FEATURE/pstat"
49da2e3ebdSchin #include "FEATURE/execargs"
50da2e3ebdSchin #include "FEATURE/externs"
51da2e3ebdSchin #ifdef _hdr_nc
52da2e3ebdSchin # include <nc.h>
53da2e3ebdSchin #endif /* _hdr_nc */
54da2e3ebdSchin
55da2e3ebdSchin #define CMD_LENGTH 64
56da2e3ebdSchin
57da2e3ebdSchin /* These routines are referenced by this module */
58da2e3ebdSchin static void exfile(Shell_t*, Sfio_t*,int);
59da2e3ebdSchin static void chkmail(Shell_t *shp, char*);
60da2e3ebdSchin #if defined(_lib_fork) && !defined(_NEXT_SOURCE)
61da2e3ebdSchin static void fixargs(char**,int);
62da2e3ebdSchin #else
63da2e3ebdSchin # define fixargs(a,b)
64da2e3ebdSchin #endif
65da2e3ebdSchin
66da2e3ebdSchin #ifndef environ
67da2e3ebdSchin extern char **environ;
68da2e3ebdSchin #endif
69da2e3ebdSchin
70da2e3ebdSchin static struct stat lastmail;
71da2e3ebdSchin static time_t mailtime;
72da2e3ebdSchin static char beenhere = 0;
73da2e3ebdSchin
74da2e3ebdSchin #ifdef _lib_sigvec
clearsigmask(register int sig)75da2e3ebdSchin void clearsigmask(register int sig)
76da2e3ebdSchin {
77da2e3ebdSchin struct sigvec vec;
78da2e3ebdSchin if(sigvec(sig,NIL(struct sigvec*),&vec)>=0 && vec.sv_mask)
79da2e3ebdSchin {
80da2e3ebdSchin vec.sv_mask = 0;
81da2e3ebdSchin sigvec(sig,&vec,NIL(struct sigvec*));
82da2e3ebdSchin }
83da2e3ebdSchin }
84da2e3ebdSchin #endif /* _lib_sigvec */
85da2e3ebdSchin
86da2e3ebdSchin #ifdef PATH_BFPATH
87da2e3ebdSchin #define PATHCOMP NIL(Pathcomp_t*)
88da2e3ebdSchin #else
89da2e3ebdSchin #define PATHCOMP ""
90da2e3ebdSchin #endif
91da2e3ebdSchin
92da2e3ebdSchin /*
93da2e3ebdSchin * search for file and exfile() it if it exists
94da2e3ebdSchin * 1 returned if file found, 0 otherwise
95da2e3ebdSchin */
96da2e3ebdSchin
sh_source(Shell_t * shp,Sfio_t * iop,const char * file)97da2e3ebdSchin int sh_source(Shell_t *shp, Sfio_t *iop, const char *file)
98da2e3ebdSchin {
99da2e3ebdSchin char* oid;
100da2e3ebdSchin char* nid;
101da2e3ebdSchin int fd;
102da2e3ebdSchin
103*b30d1939SAndy Fiddaman if (!file || !*file || (fd = path_open(shp,file, PATHCOMP)) < 0)
10434f9b3eeSRoland Mainz {
10534f9b3eeSRoland Mainz REGRESS(source, "sh_source", ("%s:ENOENT", file));
106da2e3ebdSchin return 0;
10734f9b3eeSRoland Mainz }
108da2e3ebdSchin oid = error_info.id;
109da2e3ebdSchin nid = error_info.id = strdup(file);
110*b30d1939SAndy Fiddaman shp->st.filename = path_fullname(shp,stakptr(PATH_OFFSET));
11134f9b3eeSRoland Mainz REGRESS(source, "sh_source", ("%s", file));
112da2e3ebdSchin exfile(shp, iop, fd);
113da2e3ebdSchin error_info.id = oid;
114da2e3ebdSchin free(nid);
115da2e3ebdSchin return 1;
116da2e3ebdSchin }
117da2e3ebdSchin
118da2e3ebdSchin #ifdef S_ISSOCK
119da2e3ebdSchin #define REMOTE(m) (S_ISSOCK(m)||!(m))
120da2e3ebdSchin #else
121da2e3ebdSchin #define REMOTE(m) !(m)
122da2e3ebdSchin #endif
123da2e3ebdSchin
sh_main(int ac,char * av[],Shinit_f userinit)1247c2fbfb3SApril Chin int sh_main(int ac, char *av[], Shinit_f userinit)
125da2e3ebdSchin {
126da2e3ebdSchin register char *name;
127da2e3ebdSchin register int fdin;
128da2e3ebdSchin register Sfio_t *iop;
129da2e3ebdSchin register Shell_t *shp;
130da2e3ebdSchin struct stat statb;
131da2e3ebdSchin int i, rshflag; /* set for restricted shell */
132da2e3ebdSchin char *command;
133*b30d1939SAndy Fiddaman free(malloc(64*1024));
134da2e3ebdSchin #ifdef _lib_sigvec
1357c2fbfb3SApril Chin /* This is to clear mask that may be left on by rlogin */
136da2e3ebdSchin clearsigmask(SIGALRM);
137da2e3ebdSchin clearsigmask(SIGHUP);
138da2e3ebdSchin clearsigmask(SIGCHLD);
139da2e3ebdSchin #endif /* _lib_sigvec */
140da2e3ebdSchin #ifdef _hdr_nc
141da2e3ebdSchin _NutConf(_NC_SET_SUFFIXED_SEARCHING, 1);
142da2e3ebdSchin #endif /* _hdr_nc */
143da2e3ebdSchin fixargs(av,0);
144da2e3ebdSchin shp = sh_init(ac,av,userinit);
145da2e3ebdSchin time(&mailtime);
146da2e3ebdSchin if(rshflag=sh_isoption(SH_RESTRICTED))
147da2e3ebdSchin sh_offoption(SH_RESTRICTED);
148da2e3ebdSchin if(sigsetjmp(*((sigjmp_buf*)shp->jmpbuffer),0))
149da2e3ebdSchin {
150da2e3ebdSchin /* begin script execution here */
151da2e3ebdSchin sh_reinit((char**)0);
152*b30d1939SAndy Fiddaman shp->gd->pid = getpid();
153*b30d1939SAndy Fiddaman shp->gd->ppid = getppid();
154da2e3ebdSchin }
155da2e3ebdSchin shp->fn_depth = shp->dot_depth = 0;
156da2e3ebdSchin command = error_info.id;
157da2e3ebdSchin /* set pidname '$$' */
158*b30d1939SAndy Fiddaman srand(shp->gd->pid&0x7fff);
159da2e3ebdSchin if(nv_isnull(PS4NOD))
160da2e3ebdSchin nv_putval(PS4NOD,e_traceprompt,NV_RDONLY);
161*b30d1939SAndy Fiddaman path_pwd(shp,1);
162da2e3ebdSchin iop = (Sfio_t*)0;
163da2e3ebdSchin #if SHOPT_BRACEPAT
164da2e3ebdSchin sh_onoption(SH_BRACEEXPAND);
165da2e3ebdSchin #endif
166da2e3ebdSchin if((beenhere++)==0)
167da2e3ebdSchin {
168da2e3ebdSchin sh_onstate(SH_PROFILE);
16934f9b3eeSRoland Mainz ((Lex_t*)shp->lex_context)->nonstandard = 0;
170*b30d1939SAndy Fiddaman if(shp->gd->ppid==1)
171da2e3ebdSchin shp->login_sh++;
172da2e3ebdSchin if(shp->login_sh >= 2)
173da2e3ebdSchin sh_onoption(SH_LOGIN_SHELL);
174da2e3ebdSchin /* decide whether shell is interactive */
1757c2fbfb3SApril Chin if(!sh_isoption(SH_INTERACTIVE) && !sh_isoption(SH_TFLAG) && !sh_isoption(SH_CFLAG) &&
1767c2fbfb3SApril Chin sh_isoption(SH_SFLAG) && tty_check(0) && tty_check(ERRIO))
177da2e3ebdSchin sh_onoption(SH_INTERACTIVE);
1787c2fbfb3SApril Chin if(sh_isoption(SH_INTERACTIVE))
1797c2fbfb3SApril Chin {
180da2e3ebdSchin sh_onoption(SH_BGNICE);
181da2e3ebdSchin sh_onoption(SH_RC);
182da2e3ebdSchin }
183da2e3ebdSchin if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
184da2e3ebdSchin #if SHOPT_REMOTE
185da2e3ebdSchin || !fstat(0, &statb) && REMOTE(statb.st_mode)
186da2e3ebdSchin #endif
187da2e3ebdSchin ))
188da2e3ebdSchin sh_onoption(SH_RC);
1897c2fbfb3SApril Chin for(i=0; i<elementsof(shp->offoptions.v); i++)
1907c2fbfb3SApril Chin shp->options.v[i] &= ~shp->offoptions.v[i];
191da2e3ebdSchin if(sh_isoption(SH_INTERACTIVE))
192da2e3ebdSchin {
193da2e3ebdSchin #ifdef SIGXCPU
194da2e3ebdSchin signal(SIGXCPU,SIG_DFL);
195da2e3ebdSchin #endif /* SIGXCPU */
196da2e3ebdSchin #ifdef SIGXFSZ
197da2e3ebdSchin signal(SIGXFSZ,SIG_DFL);
198da2e3ebdSchin #endif /* SIGXFSZ */
199da2e3ebdSchin sh_onoption(SH_MONITOR);
200da2e3ebdSchin }
2017c2fbfb3SApril Chin job_init(shp,sh_isoption(SH_LOGIN_SHELL));
2027c2fbfb3SApril Chin if(sh_isoption(SH_LOGIN_SHELL))
203da2e3ebdSchin {
204da2e3ebdSchin /* system profile */
205da2e3ebdSchin sh_source(shp, iop, e_sysprofile);
206da2e3ebdSchin if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED))
207da2e3ebdSchin {
208*b30d1939SAndy Fiddaman char **files = shp->gd->login_files;
2097c2fbfb3SApril Chin while ((name = *files++) && !sh_source(shp, iop, sh_mactry(shp,name)));
210da2e3ebdSchin }
211da2e3ebdSchin }
212da2e3ebdSchin /* make sure PWD is set up correctly */
213*b30d1939SAndy Fiddaman path_pwd(shp,1);
214da2e3ebdSchin if(!sh_isoption(SH_NOEXEC))
215da2e3ebdSchin {
216da2e3ebdSchin if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
217da2e3ebdSchin {
218da2e3ebdSchin #if SHOPT_BASH
219da2e3ebdSchin if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
220da2e3ebdSchin {
221da2e3ebdSchin #if SHOPT_SYSRC
222da2e3ebdSchin sh_source(shp, iop, e_bash_sysrc);
223da2e3ebdSchin #endif
224*b30d1939SAndy Fiddaman sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc));
225da2e3ebdSchin }
226da2e3ebdSchin else
227da2e3ebdSchin #endif
228da2e3ebdSchin {
2297c2fbfb3SApril Chin if(name = sh_mactry(shp,nv_getval(ENVNOD)))
2307c2fbfb3SApril Chin name = *name ? strdup(name) : (char*)0;
231da2e3ebdSchin #if SHOPT_SYSRC
2327c2fbfb3SApril Chin if(!strmatch(name, "?(.)/./*"))
2337c2fbfb3SApril Chin sh_source(shp, iop, e_sysrc);
234da2e3ebdSchin #endif
2357c2fbfb3SApril Chin if(name)
2367c2fbfb3SApril Chin {
2377c2fbfb3SApril Chin sh_source(shp, iop, name);
2387c2fbfb3SApril Chin free(name);
2397c2fbfb3SApril Chin }
240da2e3ebdSchin }
241da2e3ebdSchin }
242da2e3ebdSchin else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
243da2e3ebdSchin sh_source(shp, iop, e_suidprofile);
244da2e3ebdSchin }
245da2e3ebdSchin shp->st.cmdname = error_info.id = command;
246da2e3ebdSchin sh_offstate(SH_PROFILE);
247da2e3ebdSchin if(rshflag)
248da2e3ebdSchin sh_onoption(SH_RESTRICTED);
249da2e3ebdSchin /* open input file if specified */
250da2e3ebdSchin if(shp->comdiv)
251da2e3ebdSchin {
252da2e3ebdSchin shell_c:
253da2e3ebdSchin iop = sfnew(NIL(Sfio_t*),shp->comdiv,strlen(shp->comdiv),0,SF_STRING|SF_READ);
254da2e3ebdSchin }
255da2e3ebdSchin else
256da2e3ebdSchin {
257da2e3ebdSchin name = error_info.id;
258da2e3ebdSchin error_info.id = shp->shname;
259da2e3ebdSchin if(sh_isoption(SH_SFLAG))
260da2e3ebdSchin fdin = 0;
261da2e3ebdSchin else
262da2e3ebdSchin {
263da2e3ebdSchin char *sp;
264da2e3ebdSchin /* open stream should have been passed into shell */
265da2e3ebdSchin if(strmatch(name,e_devfdNN))
266da2e3ebdSchin {
26734f9b3eeSRoland Mainz #if !_WINIX
268da2e3ebdSchin char *cp;
269da2e3ebdSchin int type;
27034f9b3eeSRoland Mainz #endif
271da2e3ebdSchin fdin = (int)strtol(name+8, (char**)0, 10);
272da2e3ebdSchin if(fstat(fdin,&statb)<0)
2737c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_system(1),e_open,name);
274da2e3ebdSchin #if !_WINIX
275da2e3ebdSchin /*
276da2e3ebdSchin * try to undo effect of solaris 2.5+
277da2e3ebdSchin * change for argv for setuid scripts
278da2e3ebdSchin */
279*b30d1939SAndy Fiddaman if (shp->st.repl_index > 0)
280*b30d1939SAndy Fiddaman av[shp->st.repl_index] = shp->st.repl_arg;
281*b30d1939SAndy Fiddaman if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (name = nv_getval(L_ARGNOD)) && (!((type = sh_type(cp = name)) & SH_TYPE_SH)))
282da2e3ebdSchin {
283da2e3ebdSchin av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp);
284da2e3ebdSchin /* exec to change $0 for ps */
285da2e3ebdSchin execv(pathshell(),av);
286da2e3ebdSchin /* exec fails */
287da2e3ebdSchin shp->st.dolv[0] = av[0];
288da2e3ebdSchin fixargs(shp->st.dolv,1);
289da2e3ebdSchin }
290da2e3ebdSchin #endif
291da2e3ebdSchin name = av[0];
292da2e3ebdSchin sh_offoption(SH_VERBOSE);
293da2e3ebdSchin sh_offoption(SH_XTRACE);
294da2e3ebdSchin }
295da2e3ebdSchin else
296da2e3ebdSchin {
297da2e3ebdSchin int isdir = 0;
298da2e3ebdSchin if((fdin=sh_open(name,O_RDONLY,0))>=0 &&(fstat(fdin,&statb)<0 || S_ISDIR(statb.st_mode)))
299da2e3ebdSchin {
300da2e3ebdSchin close(fdin);
301da2e3ebdSchin isdir = 1;
302da2e3ebdSchin fdin = -1;
303da2e3ebdSchin }
304da2e3ebdSchin else
305*b30d1939SAndy Fiddaman shp->st.filename = path_fullname(shp,name);
306da2e3ebdSchin sp = 0;
307da2e3ebdSchin if(fdin < 0 && !strchr(name,'/'))
308da2e3ebdSchin {
309da2e3ebdSchin #ifdef PATH_BFPATH
310*b30d1939SAndy Fiddaman if(path_absolute(shp,name,NIL(Pathcomp_t*)))
311da2e3ebdSchin sp = stakptr(PATH_OFFSET);
312da2e3ebdSchin #else
313*b30d1939SAndy Fiddaman sp = path_absolute(shp,name,NIL(char*));
314da2e3ebdSchin #endif
315da2e3ebdSchin if(sp)
316da2e3ebdSchin {
317da2e3ebdSchin if((fdin=sh_open(sp,O_RDONLY,0))>=0)
318*b30d1939SAndy Fiddaman shp->st.filename = path_fullname(shp,sp);
319da2e3ebdSchin }
320da2e3ebdSchin }
321da2e3ebdSchin if(fdin<0)
322da2e3ebdSchin {
323da2e3ebdSchin if(isdir)
324da2e3ebdSchin errno = EISDIR;
325da2e3ebdSchin error_info.id = av[0];
326da2e3ebdSchin if(sp || errno!=ENOENT)
327da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_open,name);
328da2e3ebdSchin /* try sh -c 'name "$@"' */
329da2e3ebdSchin sh_onoption(SH_CFLAG);
330da2e3ebdSchin shp->comdiv = (char*)malloc(strlen(name)+7);
331da2e3ebdSchin name = strcopy(shp->comdiv,name);
332da2e3ebdSchin if(shp->st.dolc)
333da2e3ebdSchin strcopy(name," \"$@\"");
334da2e3ebdSchin goto shell_c;
335da2e3ebdSchin }
336da2e3ebdSchin if(fdin==0)
337da2e3ebdSchin fdin = sh_iomovefd(fdin);
338da2e3ebdSchin }
339da2e3ebdSchin shp->readscript = shp->shname;
340da2e3ebdSchin }
341da2e3ebdSchin error_info.id = name;
342da2e3ebdSchin shp->comdiv--;
343da2e3ebdSchin #if SHOPT_ACCT
344da2e3ebdSchin sh_accinit();
345da2e3ebdSchin if(fdin != 0)
346da2e3ebdSchin sh_accbegin(error_info.id);
347da2e3ebdSchin #endif /* SHOPT_ACCT */
348da2e3ebdSchin }
349da2e3ebdSchin }
350da2e3ebdSchin else
351da2e3ebdSchin {
352da2e3ebdSchin fdin = shp->infd;
353da2e3ebdSchin fixargs(shp->st.dolv,1);
354da2e3ebdSchin }
355da2e3ebdSchin if(sh_isoption(SH_INTERACTIVE))
356da2e3ebdSchin sh_onstate(SH_INTERACTIVE);
357da2e3ebdSchin nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
358da2e3ebdSchin exfile(shp,iop,fdin);
3597c2fbfb3SApril Chin sh_done(shp,0);
360da2e3ebdSchin /* NOTREACHED */
361da2e3ebdSchin return(0);
362da2e3ebdSchin }
363da2e3ebdSchin
364da2e3ebdSchin /*
365da2e3ebdSchin * iop is not null when the input is a string
366da2e3ebdSchin * fdin is the input file descriptor
367da2e3ebdSchin */
368da2e3ebdSchin
exfile(register Shell_t * shp,register Sfio_t * iop,register int fno)369da2e3ebdSchin static void exfile(register Shell_t *shp, register Sfio_t *iop,register int fno)
370da2e3ebdSchin {
371da2e3ebdSchin time_t curtime;
372da2e3ebdSchin Shnode_t *t;
373da2e3ebdSchin int maxtry=IOMAXTRY, tdone=0, execflags;
374da2e3ebdSchin int states,jmpval;
375da2e3ebdSchin struct checkpt buff;
376*b30d1939SAndy Fiddaman sh_pushcontext(shp,&buff,SH_JMPERREXIT);
377da2e3ebdSchin /* open input stream */
378da2e3ebdSchin nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
379da2e3ebdSchin if(!iop)
380da2e3ebdSchin {
381da2e3ebdSchin if(fno > 0)
382da2e3ebdSchin {
383da2e3ebdSchin int r;
384*b30d1939SAndy Fiddaman VALIDATE_FD(shp, fno);
385da2e3ebdSchin if(fno < 10 && ((r=sh_fcntl(fno,F_DUPFD,10))>=10))
386da2e3ebdSchin {
387*b30d1939SAndy Fiddaman VALIDATE_FD(shp, r);
388da2e3ebdSchin shp->fdstatus[r] = shp->fdstatus[fno];
389da2e3ebdSchin sh_close(fno);
390da2e3ebdSchin fno = r;
391da2e3ebdSchin }
392da2e3ebdSchin fcntl(fno,F_SETFD,FD_CLOEXEC);
393da2e3ebdSchin shp->fdstatus[fno] |= IOCLEX;
3947c2fbfb3SApril Chin iop = sh_iostream((void*)shp,fno);
395da2e3ebdSchin }
396da2e3ebdSchin else
397da2e3ebdSchin iop = sfstdin;
398da2e3ebdSchin }
399da2e3ebdSchin else
400da2e3ebdSchin fno = -1;
401da2e3ebdSchin shp->infd = fno;
402da2e3ebdSchin if(sh_isstate(SH_INTERACTIVE))
403da2e3ebdSchin {
404da2e3ebdSchin if(nv_isnull(PS1NOD))
405*b30d1939SAndy Fiddaman nv_putval(PS1NOD,(shp->gd->euserid?e_stdprompt:e_supprompt),NV_RDONLY);
406da2e3ebdSchin sh_sigdone();
4077c2fbfb3SApril Chin if(sh_histinit((void*)shp))
408da2e3ebdSchin sh_onoption(SH_HISTORY);
409da2e3ebdSchin }
410da2e3ebdSchin else
411da2e3ebdSchin {
412da2e3ebdSchin if(!sh_isstate(SH_PROFILE))
413da2e3ebdSchin {
414da2e3ebdSchin buff.mode = SH_JMPEXIT;
415da2e3ebdSchin sh_onoption(SH_TRACKALL);
416da2e3ebdSchin sh_offoption(SH_MONITOR);
417da2e3ebdSchin }
418da2e3ebdSchin sh_offstate(SH_INTERACTIVE);
419da2e3ebdSchin sh_offstate(SH_MONITOR);
420da2e3ebdSchin sh_offstate(SH_HISTORY);
421da2e3ebdSchin sh_offoption(SH_HISTORY);
422da2e3ebdSchin }
423da2e3ebdSchin states = sh_getstate();
424da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
425da2e3ebdSchin if(jmpval)
426da2e3ebdSchin {
427da2e3ebdSchin Sfio_t *top;
4287c2fbfb3SApril Chin sh_iorestore((void*)shp,0,jmpval);
429*b30d1939SAndy Fiddaman hist_flush(shp->gd->hist_ptr);
430da2e3ebdSchin sfsync(shp->outpool);
431da2e3ebdSchin shp->st.execbrk = shp->st.breakcnt = 0;
432da2e3ebdSchin /* check for return from profile or env file */
433da2e3ebdSchin if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT))
4343e14f97fSRoger A. Faulkner {
4353e14f97fSRoger A. Faulkner sh_setstate(states);
436da2e3ebdSchin goto done;
4373e14f97fSRoger A. Faulkner }
4387c2fbfb3SApril Chin if(!sh_isoption(SH_INTERACTIVE) || sh_isstate(SH_FORKED) || (jmpval > SH_JMPERREXIT && job_close(shp) >=0))
439da2e3ebdSchin {
440da2e3ebdSchin sh_offstate(SH_INTERACTIVE);
441da2e3ebdSchin sh_offstate(SH_MONITOR);
442da2e3ebdSchin goto done;
443da2e3ebdSchin }
444*b30d1939SAndy Fiddaman exitset();
445da2e3ebdSchin /* skip over remaining input */
446da2e3ebdSchin if(top = fcfile())
447da2e3ebdSchin {
448da2e3ebdSchin while(fcget()>0);
449da2e3ebdSchin fcclose();
450da2e3ebdSchin while(top=sfstack(iop,SF_POPSTACK))
451da2e3ebdSchin sfclose(top);
452da2e3ebdSchin }
453da2e3ebdSchin /* make sure that we own the terminal */
454da2e3ebdSchin #ifdef SIGTSTP
455*b30d1939SAndy Fiddaman tcsetpgrp(job.fd,shp->gd->pid);
456da2e3ebdSchin #endif /* SIGTSTP */
457da2e3ebdSchin }
458da2e3ebdSchin /* error return here */
459da2e3ebdSchin sfclrerr(iop);
460da2e3ebdSchin sh_setstate(states);
461da2e3ebdSchin shp->st.optindex = 1;
462da2e3ebdSchin opt_info.offset = 0;
463da2e3ebdSchin shp->st.loopcnt = 0;
464da2e3ebdSchin shp->trapnote = 0;
465da2e3ebdSchin shp->intrap = 0;
466da2e3ebdSchin error_info.line = 1;
467da2e3ebdSchin shp->inlineno = 1;
468da2e3ebdSchin shp->binscript = 0;
469*b30d1939SAndy Fiddaman shp->exittrap = 0;
470*b30d1939SAndy Fiddaman shp->errtrap = 0;
471*b30d1939SAndy Fiddaman shp->end_fn = 0;
472da2e3ebdSchin if(sfeof(iop))
473da2e3ebdSchin goto eof_or_error;
474da2e3ebdSchin /* command loop */
475da2e3ebdSchin while(1)
476da2e3ebdSchin {
477da2e3ebdSchin shp->nextprompt = 1;
4787c2fbfb3SApril Chin sh_freeup(shp);
479da2e3ebdSchin stakset(NIL(char*),0);
480da2e3ebdSchin sh_offstate(SH_STOPOK);
481da2e3ebdSchin sh_offstate(SH_ERREXIT);
482da2e3ebdSchin sh_offstate(SH_VERBOSE);
483da2e3ebdSchin sh_offstate(SH_TIMING);
484da2e3ebdSchin sh_offstate(SH_GRACE);
485da2e3ebdSchin sh_offstate(SH_TTYWAIT);
486da2e3ebdSchin if(sh_isoption(SH_VERBOSE))
487da2e3ebdSchin sh_onstate(SH_VERBOSE);
488da2e3ebdSchin sh_onstate(SH_ERREXIT);
489da2e3ebdSchin /* -eim flags don't apply to profiles */
490da2e3ebdSchin if(sh_isstate(SH_PROFILE))
491da2e3ebdSchin {
492da2e3ebdSchin sh_offstate(SH_INTERACTIVE);
493da2e3ebdSchin sh_offstate(SH_ERREXIT);
494da2e3ebdSchin sh_offstate(SH_MONITOR);
495da2e3ebdSchin }
496da2e3ebdSchin if(sh_isstate(SH_INTERACTIVE) && !tdone)
497da2e3ebdSchin {
498da2e3ebdSchin register char *mail;
499da2e3ebdSchin #ifdef JOBS
500da2e3ebdSchin sh_offstate(SH_MONITOR);
501da2e3ebdSchin if(sh_isoption(SH_MONITOR))
502da2e3ebdSchin sh_onstate(SH_MONITOR);
503da2e3ebdSchin if(job.pwlist)
504da2e3ebdSchin {
505da2e3ebdSchin job_walk(sfstderr,job_list,JOB_NFLAG,(char**)0);
506da2e3ebdSchin job_wait((pid_t)0);
507da2e3ebdSchin }
508da2e3ebdSchin #endif /* JOBS */
509da2e3ebdSchin if((mail=nv_getval(MAILPNOD)) || (mail=nv_getval(MAILNOD)))
510da2e3ebdSchin {
511da2e3ebdSchin time(&curtime);
512da2e3ebdSchin if ((curtime - mailtime) >= sh_mailchk)
513da2e3ebdSchin {
514da2e3ebdSchin chkmail(shp,mail);
515da2e3ebdSchin mailtime = curtime;
516da2e3ebdSchin }
517da2e3ebdSchin }
518*b30d1939SAndy Fiddaman if(shp->gd->hist_ptr)
519*b30d1939SAndy Fiddaman hist_eof(shp->gd->hist_ptr);
520da2e3ebdSchin /* sets timeout for command entry */
521da2e3ebdSchin shp->timeout = shp->st.tmout;
522da2e3ebdSchin #if SHOPT_TIMEOUT
523da2e3ebdSchin if(shp->timeout <= 0 || shp->timeout > SHOPT_TIMEOUT)
524da2e3ebdSchin shp->timeout = SHOPT_TIMEOUT;
525da2e3ebdSchin #endif /* SHOPT_TIMEOUT */
526da2e3ebdSchin shp->inlineno = 1;
527da2e3ebdSchin error_info.line = 1;
528da2e3ebdSchin shp->trapnote = 0;
529da2e3ebdSchin if(buff.mode == SH_JMPEXIT)
530da2e3ebdSchin {
531da2e3ebdSchin buff.mode = SH_JMPERREXIT;
532da2e3ebdSchin #ifdef DEBUG
533da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),"%d: mode changed to JMP_EXIT",getpid());
534da2e3ebdSchin #endif
535da2e3ebdSchin }
536da2e3ebdSchin }
537da2e3ebdSchin errno = 0;
538da2e3ebdSchin if(tdone || !sfreserve(iop,0,0))
539da2e3ebdSchin {
540da2e3ebdSchin eof_or_error:
541da2e3ebdSchin if(sh_isstate(SH_INTERACTIVE) && !sferror(iop))
542da2e3ebdSchin {
543da2e3ebdSchin if(--maxtry>0 && sh_isoption(SH_IGNOREEOF) &&
544da2e3ebdSchin !sferror(sfstderr) && (shp->fdstatus[fno]&IOTTY))
545da2e3ebdSchin {
546da2e3ebdSchin sfclrerr(iop);
547da2e3ebdSchin errormsg(SH_DICT,0,e_logout);
548da2e3ebdSchin continue;
549da2e3ebdSchin }
5507c2fbfb3SApril Chin else if(job_close(shp)<0)
551da2e3ebdSchin continue;
552da2e3ebdSchin }
553da2e3ebdSchin if(errno==0 && sferror(iop) && --maxtry>0)
554da2e3ebdSchin {
555da2e3ebdSchin sfclrlock(iop);
556da2e3ebdSchin sfclrerr(iop);
557da2e3ebdSchin continue;
558da2e3ebdSchin }
559da2e3ebdSchin goto done;
560da2e3ebdSchin }
561*b30d1939SAndy Fiddaman shp->exitval = sh.savexit;
562da2e3ebdSchin maxtry = IOMAXTRY;
563*b30d1939SAndy Fiddaman if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
564da2e3ebdSchin {
565da2e3ebdSchin job_wait((pid_t)0);
566*b30d1939SAndy Fiddaman hist_eof(shp->gd->hist_ptr);
567da2e3ebdSchin sfsync(sfstderr);
568da2e3ebdSchin }
569da2e3ebdSchin if(sh_isoption(SH_HISTORY))
570da2e3ebdSchin sh_onstate(SH_HISTORY);
571da2e3ebdSchin job.waitall = job.curpgid = 0;
572da2e3ebdSchin error_info.flags |= ERROR_INTERACTIVE;
573da2e3ebdSchin t = (Shnode_t*)sh_parse(shp,iop,0);
574*b30d1939SAndy Fiddaman if(!sh_isstate(SH_INTERACTIVE) && !sh_isoption(SH_CFLAG))
575da2e3ebdSchin error_info.flags &= ~ERROR_INTERACTIVE;
576da2e3ebdSchin shp->readscript = 0;
577*b30d1939SAndy Fiddaman if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
578*b30d1939SAndy Fiddaman hist_flush(shp->gd->hist_ptr);
579da2e3ebdSchin sh_offstate(SH_HISTORY);
580da2e3ebdSchin if(t)
581da2e3ebdSchin {
582da2e3ebdSchin execflags = sh_state(SH_ERREXIT)|sh_state(SH_INTERACTIVE);
583da2e3ebdSchin shp->st.execbrk = 0;
584da2e3ebdSchin sh_exec(t,execflags);
585da2e3ebdSchin if(shp->forked)
586da2e3ebdSchin {
587da2e3ebdSchin sh_offstate(SH_INTERACTIVE);
588da2e3ebdSchin goto done;
589da2e3ebdSchin }
590da2e3ebdSchin /* This is for sh -t */
591da2e3ebdSchin if(sh_isoption(SH_TFLAG) && !sh_isstate(SH_PROFILE))
592da2e3ebdSchin tdone++;
593da2e3ebdSchin }
594da2e3ebdSchin }
595da2e3ebdSchin done:
596*b30d1939SAndy Fiddaman sh_popcontext(shp,&buff);
597da2e3ebdSchin if(sh_isstate(SH_INTERACTIVE))
598da2e3ebdSchin {
599da2e3ebdSchin sfputc(sfstderr,'\n');
6007c2fbfb3SApril Chin job_close(shp);
601da2e3ebdSchin }
602da2e3ebdSchin if(jmpval == SH_JMPSCRIPT)
603da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
604da2e3ebdSchin else if(jmpval == SH_JMPEXIT)
6057c2fbfb3SApril Chin sh_done(shp,0);
606da2e3ebdSchin if(fno>0)
607da2e3ebdSchin sh_close(fno);
608da2e3ebdSchin if(shp->st.filename)
609da2e3ebdSchin free((void*)shp->st.filename);
610da2e3ebdSchin shp->st.filename = 0;
611da2e3ebdSchin }
612da2e3ebdSchin
613da2e3ebdSchin
614da2e3ebdSchin /* prints out messages if files in list have been modified since last call */
chkmail(Shell_t * shp,char * files)615da2e3ebdSchin static void chkmail(Shell_t *shp, char *files)
616da2e3ebdSchin {
617da2e3ebdSchin register char *cp,*sp,*qp;
618da2e3ebdSchin register char save;
619da2e3ebdSchin struct argnod *arglist=0;
620da2e3ebdSchin int offset = staktell();
621da2e3ebdSchin char *savstak=stakptr(0);
622da2e3ebdSchin struct stat statb;
623da2e3ebdSchin if(*(cp=files) == 0)
624da2e3ebdSchin return;
625da2e3ebdSchin sp = cp;
626da2e3ebdSchin do
627da2e3ebdSchin {
628da2e3ebdSchin /* skip to : or end of string saving first '?' */
629da2e3ebdSchin for(qp=0;*sp && *sp != ':';sp++)
630da2e3ebdSchin if((*sp == '?' || *sp=='%') && qp == 0)
631da2e3ebdSchin qp = sp;
632da2e3ebdSchin save = *sp;
633da2e3ebdSchin *sp = 0;
634da2e3ebdSchin /* change '?' to end-of-string */
635da2e3ebdSchin if(qp)
636da2e3ebdSchin *qp = 0;
637da2e3ebdSchin do
638da2e3ebdSchin {
639da2e3ebdSchin /* see if time has been modified since last checked
640da2e3ebdSchin * and the access time <= the modification time
641da2e3ebdSchin */
642da2e3ebdSchin if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime
643da2e3ebdSchin && statb.st_atime <= statb.st_mtime)
644da2e3ebdSchin {
645da2e3ebdSchin /* check for directory */
646da2e3ebdSchin if(!arglist && S_ISDIR(statb.st_mode))
647da2e3ebdSchin {
648da2e3ebdSchin /* generate list of directory entries */
649*b30d1939SAndy Fiddaman path_complete(shp,cp,"/*",&arglist);
650da2e3ebdSchin }
651da2e3ebdSchin else
652da2e3ebdSchin {
653da2e3ebdSchin /*
654da2e3ebdSchin * If the file has shrunk,
655da2e3ebdSchin * or if the size is zero
656da2e3ebdSchin * then don't print anything
657da2e3ebdSchin */
658da2e3ebdSchin if(statb.st_size &&
659da2e3ebdSchin ( statb.st_ino != lastmail.st_ino
660da2e3ebdSchin || statb.st_dev != lastmail.st_dev
661da2e3ebdSchin || statb.st_size > lastmail.st_size))
662da2e3ebdSchin {
663da2e3ebdSchin /* save and restore $_ */
664da2e3ebdSchin char *save = shp->lastarg;
665da2e3ebdSchin shp->lastarg = cp;
6667c2fbfb3SApril Chin errormsg(SH_DICT,0,sh_mactry(shp,qp?qp+1:(char*)e_mailmsg));
667da2e3ebdSchin shp->lastarg = save;
668da2e3ebdSchin }
669da2e3ebdSchin lastmail = statb;
670da2e3ebdSchin break;
671da2e3ebdSchin }
672da2e3ebdSchin }
673da2e3ebdSchin if(arglist)
674da2e3ebdSchin {
675da2e3ebdSchin cp = arglist->argval;
676da2e3ebdSchin arglist = arglist->argchn.ap;
677da2e3ebdSchin }
678da2e3ebdSchin else
679da2e3ebdSchin cp = 0;
680da2e3ebdSchin }
681da2e3ebdSchin while(cp);
682da2e3ebdSchin if(qp)
683da2e3ebdSchin *qp = '?';
684da2e3ebdSchin *sp++ = save;
685da2e3ebdSchin cp = sp;
686da2e3ebdSchin }
687da2e3ebdSchin while(save);
688da2e3ebdSchin stakset(savstak,offset);
689da2e3ebdSchin }
690da2e3ebdSchin
691da2e3ebdSchin #undef EXECARGS
692da2e3ebdSchin #undef PSTAT
693da2e3ebdSchin #if defined(_hdr_execargs) && defined(pdp11)
694da2e3ebdSchin # include <execargs.h>
695da2e3ebdSchin # define EXECARGS 1
696da2e3ebdSchin #endif
697da2e3ebdSchin
698da2e3ebdSchin #if defined(_lib_pstat) && defined(_sys_pstat)
699da2e3ebdSchin # include <sys/pstat.h>
700da2e3ebdSchin # define PSTAT 1
701da2e3ebdSchin #endif
702da2e3ebdSchin
703da2e3ebdSchin #if defined(_lib_fork) && !defined(_NEXT_SOURCE)
704da2e3ebdSchin /*
705da2e3ebdSchin * fix up command line for ps command
706da2e3ebdSchin * mode is 0 for initialization
707da2e3ebdSchin */
fixargs(char ** argv,int mode)708da2e3ebdSchin static void fixargs(char **argv, int mode)
709da2e3ebdSchin {
710da2e3ebdSchin #if EXECARGS
711da2e3ebdSchin *execargs=(char *)argv;
712da2e3ebdSchin #else
713da2e3ebdSchin static char *buff;
714da2e3ebdSchin static int command_len;
715da2e3ebdSchin register char *cp;
716da2e3ebdSchin int offset=0,size;
717da2e3ebdSchin # ifdef PSTAT
718da2e3ebdSchin union pstun un;
719da2e3ebdSchin if(mode==0)
720da2e3ebdSchin {
721da2e3ebdSchin struct pst_static st;
722da2e3ebdSchin un.pst_static = &st;
723da2e3ebdSchin if(pstat(PSTAT_STATIC, un, sizeof(struct pst_static), 1, 0)<0)
724da2e3ebdSchin return;
725da2e3ebdSchin command_len = st.command_length;
726da2e3ebdSchin return;
727da2e3ebdSchin }
728da2e3ebdSchin stakseek(command_len+2);
729da2e3ebdSchin buff = stakseek(0);
730da2e3ebdSchin # else
731da2e3ebdSchin if(mode==0)
732da2e3ebdSchin {
733da2e3ebdSchin buff = argv[0];
734da2e3ebdSchin while(cp = *argv++)
735da2e3ebdSchin command_len += strlen(cp)+1;
736da2e3ebdSchin if(environ && *environ==buff+command_len)
737da2e3ebdSchin {
738da2e3ebdSchin for(argv=environ; cp = *argv; cp++)
739da2e3ebdSchin {
740da2e3ebdSchin if(command_len > CMD_LENGTH)
741da2e3ebdSchin {
742da2e3ebdSchin command_len = CMD_LENGTH;
743da2e3ebdSchin break;
744da2e3ebdSchin }
745da2e3ebdSchin *argv++ = strdup(cp);
746da2e3ebdSchin command_len += strlen(cp)+1;
747da2e3ebdSchin }
748da2e3ebdSchin }
749da2e3ebdSchin command_len -= 1;
750da2e3ebdSchin return;
751da2e3ebdSchin }
752da2e3ebdSchin # endif /* PSTAT */
753da2e3ebdSchin if(command_len==0)
754da2e3ebdSchin return;
755da2e3ebdSchin while((cp = *argv++) && offset < command_len)
756da2e3ebdSchin {
757da2e3ebdSchin if(offset + (size=strlen(cp)) >= command_len)
758da2e3ebdSchin size = command_len - offset;
759da2e3ebdSchin memcpy(buff+offset,cp,size);
760da2e3ebdSchin offset += size;
761da2e3ebdSchin buff[offset++] = ' ';
762da2e3ebdSchin }
763da2e3ebdSchin buff[offset-1] = 0;
764da2e3ebdSchin # ifdef PSTAT
765da2e3ebdSchin un.pst_command = stakptr(0);
766da2e3ebdSchin pstat(PSTAT_SETCMD,un,0,0,0);
767da2e3ebdSchin # endif /* PSTAT */
768da2e3ebdSchin #endif /* EXECARGS */
769da2e3ebdSchin }
770da2e3ebdSchin #endif /* _lib_fork */
771