14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * UNIX shell
234887Schin *
244887Schin * S. R. Bourne
254887Schin * Rewritten By David Korn
264887Schin * AT&T Labs
274887Schin *
284887Schin */
294887Schin
304887Schin #include <ast.h>
314887Schin #include <sfio.h>
324887Schin #include <stak.h>
334887Schin #include <ls.h>
344887Schin #include <fcin.h>
354887Schin #include "defs.h"
364887Schin #include "variables.h"
374887Schin #include "path.h"
384887Schin #include "io.h"
394887Schin #include "jobs.h"
4010898Sroland.mainz@nrubsig.org #include "shlex.h"
414887Schin #include "shnodes.h"
424887Schin #include "history.h"
434887Schin #include "timeout.h"
444887Schin #include "FEATURE/time"
454887Schin #include "FEATURE/pstat"
464887Schin #include "FEATURE/execargs"
474887Schin #include "FEATURE/externs"
484887Schin #ifdef _hdr_nc
494887Schin # include <nc.h>
504887Schin #endif /* _hdr_nc */
514887Schin
524887Schin #define CMD_LENGTH 64
534887Schin
544887Schin /* These routines are referenced by this module */
554887Schin static void exfile(Shell_t*, Sfio_t*,int);
564887Schin static void chkmail(Shell_t *shp, char*);
574887Schin #if defined(_lib_fork) && !defined(_NEXT_SOURCE)
584887Schin static void fixargs(char**,int);
594887Schin #else
604887Schin # define fixargs(a,b)
614887Schin #endif
624887Schin
634887Schin #ifndef environ
644887Schin extern char **environ;
654887Schin #endif
664887Schin
674887Schin static struct stat lastmail;
684887Schin static time_t mailtime;
694887Schin static char beenhere = 0;
704887Schin
714887Schin #ifdef _lib_sigvec
clearsigmask(register int sig)724887Schin void clearsigmask(register int sig)
734887Schin {
744887Schin struct sigvec vec;
754887Schin if(sigvec(sig,NIL(struct sigvec*),&vec)>=0 && vec.sv_mask)
764887Schin {
774887Schin vec.sv_mask = 0;
784887Schin sigvec(sig,&vec,NIL(struct sigvec*));
794887Schin }
804887Schin }
814887Schin #endif /* _lib_sigvec */
824887Schin
834887Schin #ifdef _lib_fts_notify
844887Schin # include <fts.h>
854887Schin /* check for interrupts during tree walks */
fts_sigcheck(FTS * fp,FTSENT * ep,void * context)864887Schin static int fts_sigcheck(FTS* fp, FTSENT* ep, void* context)
874887Schin {
884887Schin Shell_t *shp = (Shell_t*)context;
894887Schin NOT_USED(fp);
904887Schin NOT_USED(ep);
914887Schin if(shp->trapnote&SH_SIGSET)
924887Schin {
934887Schin errno = EINTR;
944887Schin return(-1);
954887Schin }
964887Schin return(0);
974887Schin }
984887Schin #endif /* _lib_fts_notify */
994887Schin
1004887Schin #ifdef PATH_BFPATH
1014887Schin #define PATHCOMP NIL(Pathcomp_t*)
1024887Schin #else
1034887Schin #define PATHCOMP ""
1044887Schin #endif
1054887Schin
1064887Schin /*
1074887Schin * search for file and exfile() it if it exists
1084887Schin * 1 returned if file found, 0 otherwise
1094887Schin */
1104887Schin
sh_source(Shell_t * shp,Sfio_t * iop,const char * file)1114887Schin int sh_source(Shell_t *shp, Sfio_t *iop, const char *file)
1124887Schin {
1134887Schin char* oid;
1144887Schin char* nid;
1154887Schin int fd;
1164887Schin
1174887Schin if (!file || !*file || (fd = path_open(file, PATHCOMP)) < 0)
11810898Sroland.mainz@nrubsig.org {
11910898Sroland.mainz@nrubsig.org REGRESS(source, "sh_source", ("%s:ENOENT", file));
1204887Schin return 0;
12110898Sroland.mainz@nrubsig.org }
1224887Schin oid = error_info.id;
1234887Schin nid = error_info.id = strdup(file);
1244887Schin shp->st.filename = path_fullname(stakptr(PATH_OFFSET));
12510898Sroland.mainz@nrubsig.org REGRESS(source, "sh_source", ("%s", file));
1264887Schin exfile(shp, iop, fd);
1274887Schin error_info.id = oid;
1284887Schin free(nid);
1294887Schin return 1;
1304887Schin }
1314887Schin
1324887Schin #ifdef S_ISSOCK
1334887Schin #define REMOTE(m) (S_ISSOCK(m)||!(m))
1344887Schin #else
1354887Schin #define REMOTE(m) !(m)
1364887Schin #endif
1374887Schin
sh_main(int ac,char * av[],Shinit_f userinit)1388462SApril.Chin@Sun.COM int sh_main(int ac, char *av[], Shinit_f userinit)
1394887Schin {
1404887Schin register char *name;
1414887Schin register int fdin;
1424887Schin register Sfio_t *iop;
1434887Schin register Shell_t *shp;
1444887Schin struct stat statb;
1454887Schin int i, rshflag; /* set for restricted shell */
1464887Schin char *command;
1474887Schin #ifdef _lib_sigvec
1488462SApril.Chin@Sun.COM /* This is to clear mask that may be left on by rlogin */
1494887Schin clearsigmask(SIGALRM);
1504887Schin clearsigmask(SIGHUP);
1514887Schin clearsigmask(SIGCHLD);
1524887Schin #endif /* _lib_sigvec */
1534887Schin #ifdef _hdr_nc
1544887Schin _NutConf(_NC_SET_SUFFIXED_SEARCHING, 1);
1554887Schin #endif /* _hdr_nc */
1564887Schin fixargs(av,0);
1574887Schin shp = sh_init(ac,av,userinit);
1584887Schin time(&mailtime);
1594887Schin if(rshflag=sh_isoption(SH_RESTRICTED))
1604887Schin sh_offoption(SH_RESTRICTED);
1614887Schin #ifdef _lib_fts_notify
1624887Schin fts_notify(fts_sigcheck,(void*)shp);
1634887Schin #endif /* _lib_fts_notify */
1644887Schin if(sigsetjmp(*((sigjmp_buf*)shp->jmpbuffer),0))
1654887Schin {
1664887Schin /* begin script execution here */
1674887Schin sh_reinit((char**)0);
1684887Schin }
1694887Schin shp->fn_depth = shp->dot_depth = 0;
1704887Schin command = error_info.id;
1714887Schin /* set pidname '$$' */
1724887Schin shp->pid = getpid();
1734887Schin srand(shp->pid&0x7fff);
1744887Schin shp->ppid = getppid();
1754887Schin if(nv_isnull(PS4NOD))
1764887Schin nv_putval(PS4NOD,e_traceprompt,NV_RDONLY);
1774887Schin path_pwd(1);
1784887Schin iop = (Sfio_t*)0;
1794887Schin #if SHOPT_BRACEPAT
1804887Schin sh_onoption(SH_BRACEEXPAND);
1814887Schin #endif
1824887Schin if((beenhere++)==0)
1834887Schin {
1844887Schin sh_onstate(SH_PROFILE);
18510898Sroland.mainz@nrubsig.org ((Lex_t*)shp->lex_context)->nonstandard = 0;
1864887Schin if(shp->ppid==1)
1874887Schin shp->login_sh++;
1884887Schin if(shp->login_sh >= 2)
1894887Schin sh_onoption(SH_LOGIN_SHELL);
1904887Schin /* decide whether shell is interactive */
1918462SApril.Chin@Sun.COM if(!sh_isoption(SH_INTERACTIVE) && !sh_isoption(SH_TFLAG) && !sh_isoption(SH_CFLAG) &&
1928462SApril.Chin@Sun.COM sh_isoption(SH_SFLAG) && tty_check(0) && tty_check(ERRIO))
1938462SApril.Chin@Sun.COM sh_onoption(SH_INTERACTIVE);
1948462SApril.Chin@Sun.COM if(sh_isoption(SH_INTERACTIVE))
1954887Schin {
1964887Schin sh_onoption(SH_BGNICE);
1974887Schin sh_onoption(SH_RC);
1984887Schin }
1994887Schin if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
2004887Schin #if SHOPT_REMOTE
2014887Schin || !fstat(0, &statb) && REMOTE(statb.st_mode)
2024887Schin #endif
2034887Schin ))
2044887Schin sh_onoption(SH_RC);
2058462SApril.Chin@Sun.COM for(i=0; i<elementsof(shp->offoptions.v); i++)
2068462SApril.Chin@Sun.COM shp->options.v[i] &= ~shp->offoptions.v[i];
2074887Schin if(sh_isoption(SH_INTERACTIVE))
2084887Schin {
2094887Schin #ifdef SIGXCPU
2104887Schin signal(SIGXCPU,SIG_DFL);
2114887Schin #endif /* SIGXCPU */
2124887Schin #ifdef SIGXFSZ
2134887Schin signal(SIGXFSZ,SIG_DFL);
2144887Schin #endif /* SIGXFSZ */
2154887Schin sh_onoption(SH_MONITOR);
2164887Schin }
2178462SApril.Chin@Sun.COM job_init(shp,sh_isoption(SH_LOGIN_SHELL));
2188462SApril.Chin@Sun.COM if(sh_isoption(SH_LOGIN_SHELL))
2194887Schin {
2204887Schin /* system profile */
2214887Schin sh_source(shp, iop, e_sysprofile);
2224887Schin if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED))
2234887Schin {
2244887Schin char **files = shp->login_files;
2258462SApril.Chin@Sun.COM while ((name = *files++) && !sh_source(shp, iop, sh_mactry(shp,name)));
2264887Schin }
2274887Schin }
2284887Schin /* make sure PWD is set up correctly */
2294887Schin path_pwd(1);
2304887Schin if(!sh_isoption(SH_NOEXEC))
2314887Schin {
2324887Schin if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
2334887Schin {
2344887Schin #if SHOPT_BASH
2354887Schin if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
2364887Schin {
2374887Schin #if SHOPT_SYSRC
2384887Schin sh_source(shp, iop, e_bash_sysrc);
2394887Schin #endif
2408462SApril.Chin@Sun.COM sh_source(shp, iop, shp->rcfile ? shp->rcfile : sh_mactry(shp,(char*)e_bash_rc));
2414887Schin }
2424887Schin else
2434887Schin #endif
2444887Schin {
2458462SApril.Chin@Sun.COM if(name = sh_mactry(shp,nv_getval(ENVNOD)))
2468462SApril.Chin@Sun.COM name = *name ? strdup(name) : (char*)0;
2474887Schin #if SHOPT_SYSRC
2488462SApril.Chin@Sun.COM if(!strmatch(name, "?(.)/./*"))
2498462SApril.Chin@Sun.COM sh_source(shp, iop, e_sysrc);
2504887Schin #endif
2518462SApril.Chin@Sun.COM if(name)
2528462SApril.Chin@Sun.COM {
2538462SApril.Chin@Sun.COM sh_source(shp, iop, name);
2548462SApril.Chin@Sun.COM free(name);
2558462SApril.Chin@Sun.COM }
2564887Schin }
2574887Schin }
2584887Schin else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
2594887Schin sh_source(shp, iop, e_suidprofile);
2604887Schin }
2614887Schin shp->st.cmdname = error_info.id = command;
2624887Schin sh_offstate(SH_PROFILE);
2634887Schin if(rshflag)
2644887Schin sh_onoption(SH_RESTRICTED);
2654887Schin /* open input file if specified */
2664887Schin if(shp->comdiv)
2674887Schin {
2684887Schin shell_c:
2694887Schin iop = sfnew(NIL(Sfio_t*),shp->comdiv,strlen(shp->comdiv),0,SF_STRING|SF_READ);
2704887Schin }
2714887Schin else
2724887Schin {
2734887Schin name = error_info.id;
2744887Schin error_info.id = shp->shname;
2754887Schin if(sh_isoption(SH_SFLAG))
2764887Schin fdin = 0;
2774887Schin else
2784887Schin {
2794887Schin char *sp;
2804887Schin /* open stream should have been passed into shell */
2814887Schin if(strmatch(name,e_devfdNN))
2824887Schin {
28310898Sroland.mainz@nrubsig.org #if !_WINIX
2844887Schin char *cp;
2854887Schin int type;
28610898Sroland.mainz@nrubsig.org #endif
2874887Schin fdin = (int)strtol(name+8, (char**)0, 10);
2884887Schin if(fstat(fdin,&statb)<0)
2898462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_system(1),e_open,name);
2904887Schin #if !_WINIX
2914887Schin /*
2924887Schin * try to undo effect of solaris 2.5+
2934887Schin * change for argv for setuid scripts
2944887Schin */
2954887Schin if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (!(name = nv_getval(L_ARGNOD)) || !((type = sh_type(cp = name)) & SH_TYPE_SH)))
2964887Schin {
2974887Schin av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp);
2984887Schin /* exec to change $0 for ps */
2994887Schin execv(pathshell(),av);
3004887Schin /* exec fails */
3014887Schin shp->st.dolv[0] = av[0];
3024887Schin fixargs(shp->st.dolv,1);
3034887Schin }
3044887Schin #endif
3054887Schin name = av[0];
3064887Schin sh_offoption(SH_VERBOSE);
3074887Schin sh_offoption(SH_XTRACE);
3084887Schin }
3094887Schin else
3104887Schin {
3114887Schin int isdir = 0;
3124887Schin if((fdin=sh_open(name,O_RDONLY,0))>=0 &&(fstat(fdin,&statb)<0 || S_ISDIR(statb.st_mode)))
3134887Schin {
3144887Schin close(fdin);
3154887Schin isdir = 1;
3164887Schin fdin = -1;
3174887Schin }
3184887Schin else
3194887Schin shp->st.filename = path_fullname(name);
3204887Schin sp = 0;
3214887Schin if(fdin < 0 && !strchr(name,'/'))
3224887Schin {
3234887Schin #ifdef PATH_BFPATH
3244887Schin if(path_absolute(name,NIL(Pathcomp_t*)))
3254887Schin sp = stakptr(PATH_OFFSET);
3264887Schin #else
3274887Schin sp = path_absolute(name,NIL(char*));
3284887Schin #endif
3294887Schin if(sp)
3304887Schin {
3314887Schin if((fdin=sh_open(sp,O_RDONLY,0))>=0)
3324887Schin shp->st.filename = path_fullname(sp);
3334887Schin }
3344887Schin }
3354887Schin if(fdin<0)
3364887Schin {
3374887Schin if(isdir)
3384887Schin errno = EISDIR;
3394887Schin error_info.id = av[0];
3404887Schin if(sp || errno!=ENOENT)
3414887Schin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_open,name);
3424887Schin /* try sh -c 'name "$@"' */
3434887Schin sh_onoption(SH_CFLAG);
3444887Schin shp->comdiv = (char*)malloc(strlen(name)+7);
3454887Schin name = strcopy(shp->comdiv,name);
3464887Schin if(shp->st.dolc)
3474887Schin strcopy(name," \"$@\"");
3484887Schin goto shell_c;
3494887Schin }
3504887Schin if(fdin==0)
3514887Schin fdin = sh_iomovefd(fdin);
3524887Schin }
3534887Schin shp->readscript = shp->shname;
3544887Schin }
3554887Schin error_info.id = name;
3564887Schin shp->comdiv--;
3574887Schin #if SHOPT_ACCT
3584887Schin sh_accinit();
3594887Schin if(fdin != 0)
3604887Schin sh_accbegin(error_info.id);
3614887Schin #endif /* SHOPT_ACCT */
3624887Schin }
3634887Schin }
3644887Schin else
3654887Schin {
3664887Schin fdin = shp->infd;
3674887Schin fixargs(shp->st.dolv,1);
3684887Schin }
3694887Schin if(sh_isoption(SH_INTERACTIVE))
3704887Schin sh_onstate(SH_INTERACTIVE);
3714887Schin nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
3724887Schin exfile(shp,iop,fdin);
3738462SApril.Chin@Sun.COM sh_done(shp,0);
3744887Schin /* NOTREACHED */
3754887Schin return(0);
3764887Schin }
3774887Schin
3784887Schin /*
3794887Schin * iop is not null when the input is a string
3804887Schin * fdin is the input file descriptor
3814887Schin */
3824887Schin
exfile(register Shell_t * shp,register Sfio_t * iop,register int fno)3834887Schin static void exfile(register Shell_t *shp, register Sfio_t *iop,register int fno)
3844887Schin {
3854887Schin time_t curtime;
3864887Schin Shnode_t *t;
3874887Schin int maxtry=IOMAXTRY, tdone=0, execflags;
3884887Schin int states,jmpval;
3894887Schin struct checkpt buff;
3904887Schin sh_pushcontext(&buff,SH_JMPERREXIT);
3914887Schin /* open input stream */
3924887Schin nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
3934887Schin if(!iop)
3944887Schin {
3954887Schin if(fno > 0)
3964887Schin {
3974887Schin int r;
3984887Schin if(fno < 10 && ((r=sh_fcntl(fno,F_DUPFD,10))>=10))
3994887Schin {
4004887Schin shp->fdstatus[r] = shp->fdstatus[fno];
4014887Schin sh_close(fno);
4024887Schin fno = r;
4034887Schin }
4044887Schin fcntl(fno,F_SETFD,FD_CLOEXEC);
4054887Schin shp->fdstatus[fno] |= IOCLEX;
4068462SApril.Chin@Sun.COM iop = sh_iostream((void*)shp,fno);
4074887Schin }
4084887Schin else
4094887Schin iop = sfstdin;
4104887Schin }
4114887Schin else
4124887Schin fno = -1;
4134887Schin shp->infd = fno;
4144887Schin if(sh_isstate(SH_INTERACTIVE))
4154887Schin {
4164887Schin if(nv_isnull(PS1NOD))
4174887Schin nv_putval(PS1NOD,(shp->euserid?e_stdprompt:e_supprompt),NV_RDONLY);
4184887Schin sh_sigdone();
4198462SApril.Chin@Sun.COM if(sh_histinit((void*)shp))
4204887Schin sh_onoption(SH_HISTORY);
4214887Schin }
4224887Schin else
4234887Schin {
4244887Schin if(!sh_isstate(SH_PROFILE))
4254887Schin {
4264887Schin buff.mode = SH_JMPEXIT;
4274887Schin sh_onoption(SH_TRACKALL);
4284887Schin sh_offoption(SH_MONITOR);
4294887Schin }
4304887Schin sh_offstate(SH_INTERACTIVE);
4314887Schin sh_offstate(SH_MONITOR);
4324887Schin sh_offstate(SH_HISTORY);
4334887Schin sh_offoption(SH_HISTORY);
4344887Schin }
4354887Schin states = sh_getstate();
4364887Schin jmpval = sigsetjmp(buff.buff,0);
4374887Schin if(jmpval)
4384887Schin {
4394887Schin Sfio_t *top;
4408462SApril.Chin@Sun.COM sh_iorestore((void*)shp,0,jmpval);
4414887Schin hist_flush(shp->hist_ptr);
4424887Schin sfsync(shp->outpool);
4434887Schin shp->st.execbrk = shp->st.breakcnt = 0;
4444887Schin /* check for return from profile or env file */
4454887Schin if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT))
446*12068SRoger.Faulkner@Oracle.COM {
447*12068SRoger.Faulkner@Oracle.COM sh_setstate(states);
4484887Schin goto done;
449*12068SRoger.Faulkner@Oracle.COM }
4508462SApril.Chin@Sun.COM if(!sh_isoption(SH_INTERACTIVE) || sh_isstate(SH_FORKED) || (jmpval > SH_JMPERREXIT && job_close(shp) >=0))
4514887Schin {
4524887Schin sh_offstate(SH_INTERACTIVE);
4534887Schin sh_offstate(SH_MONITOR);
4544887Schin goto done;
4554887Schin }
4564887Schin /* skip over remaining input */
4574887Schin if(top = fcfile())
4584887Schin {
4594887Schin while(fcget()>0);
4604887Schin fcclose();
4614887Schin while(top=sfstack(iop,SF_POPSTACK))
4624887Schin sfclose(top);
4634887Schin }
4644887Schin /* make sure that we own the terminal */
4654887Schin #ifdef SIGTSTP
4664887Schin tcsetpgrp(job.fd,shp->pid);
4674887Schin #endif /* SIGTSTP */
4684887Schin }
4694887Schin /* error return here */
4704887Schin sfclrerr(iop);
4714887Schin sh_setstate(states);
4724887Schin shp->st.optindex = 1;
4734887Schin opt_info.offset = 0;
4744887Schin shp->st.loopcnt = 0;
4754887Schin shp->trapnote = 0;
4764887Schin shp->intrap = 0;
4774887Schin error_info.line = 1;
4784887Schin shp->inlineno = 1;
4794887Schin shp->binscript = 0;
4804887Schin if(sfeof(iop))
4814887Schin goto eof_or_error;
4824887Schin /* command loop */
4834887Schin while(1)
4844887Schin {
4854887Schin shp->nextprompt = 1;
4868462SApril.Chin@Sun.COM sh_freeup(shp);
4874887Schin stakset(NIL(char*),0);
4884887Schin exitset();
4894887Schin sh_offstate(SH_STOPOK);
4904887Schin sh_offstate(SH_ERREXIT);
4914887Schin sh_offstate(SH_VERBOSE);
4924887Schin sh_offstate(SH_TIMING);
4934887Schin sh_offstate(SH_GRACE);
4944887Schin sh_offstate(SH_TTYWAIT);
4954887Schin if(sh_isoption(SH_VERBOSE))
4964887Schin sh_onstate(SH_VERBOSE);
4974887Schin sh_onstate(SH_ERREXIT);
4984887Schin /* -eim flags don't apply to profiles */
4994887Schin if(sh_isstate(SH_PROFILE))
5004887Schin {
5014887Schin sh_offstate(SH_INTERACTIVE);
5024887Schin sh_offstate(SH_ERREXIT);
5034887Schin sh_offstate(SH_MONITOR);
5044887Schin }
5054887Schin if(sh_isstate(SH_INTERACTIVE) && !tdone)
5064887Schin {
5074887Schin register char *mail;
5084887Schin #ifdef JOBS
5094887Schin sh_offstate(SH_MONITOR);
5104887Schin if(sh_isoption(SH_MONITOR))
5114887Schin sh_onstate(SH_MONITOR);
5124887Schin if(job.pwlist)
5134887Schin {
5144887Schin job_walk(sfstderr,job_list,JOB_NFLAG,(char**)0);
5154887Schin job_wait((pid_t)0);
5164887Schin }
5174887Schin #endif /* JOBS */
5184887Schin if((mail=nv_getval(MAILPNOD)) || (mail=nv_getval(MAILNOD)))
5194887Schin {
5204887Schin time(&curtime);
5214887Schin if ((curtime - mailtime) >= sh_mailchk)
5224887Schin {
5234887Schin chkmail(shp,mail);
5244887Schin mailtime = curtime;
5254887Schin }
5264887Schin }
5274887Schin if(shp->hist_ptr)
5284887Schin hist_eof(shp->hist_ptr);
5294887Schin /* sets timeout for command entry */
5304887Schin shp->timeout = shp->st.tmout;
5314887Schin #if SHOPT_TIMEOUT
5324887Schin if(shp->timeout <= 0 || shp->timeout > SHOPT_TIMEOUT)
5334887Schin shp->timeout = SHOPT_TIMEOUT;
5344887Schin #endif /* SHOPT_TIMEOUT */
5354887Schin shp->inlineno = 1;
5364887Schin error_info.line = 1;
5374887Schin shp->exitval = 0;
5384887Schin shp->trapnote = 0;
5394887Schin if(buff.mode == SH_JMPEXIT)
5404887Schin {
5414887Schin buff.mode = SH_JMPERREXIT;
5424887Schin #ifdef DEBUG
5434887Schin errormsg(SH_DICT,ERROR_warn(0),"%d: mode changed to JMP_EXIT",getpid());
5444887Schin #endif
5454887Schin }
5464887Schin }
5474887Schin errno = 0;
5484887Schin if(tdone || !sfreserve(iop,0,0))
5494887Schin {
5504887Schin eof_or_error:
5514887Schin if(sh_isstate(SH_INTERACTIVE) && !sferror(iop))
5524887Schin {
5534887Schin if(--maxtry>0 && sh_isoption(SH_IGNOREEOF) &&
5544887Schin !sferror(sfstderr) && (shp->fdstatus[fno]&IOTTY))
5554887Schin {
5564887Schin sfclrerr(iop);
5574887Schin errormsg(SH_DICT,0,e_logout);
5584887Schin continue;
5594887Schin }
5608462SApril.Chin@Sun.COM else if(job_close(shp)<0)
5614887Schin continue;
5624887Schin }
5634887Schin if(errno==0 && sferror(iop) && --maxtry>0)
5644887Schin {
5654887Schin sfclrlock(iop);
5664887Schin sfclrerr(iop);
5674887Schin continue;
5684887Schin }
5694887Schin goto done;
5704887Schin }
5714887Schin maxtry = IOMAXTRY;
5724887Schin if(sh_isstate(SH_INTERACTIVE) && shp->hist_ptr)
5734887Schin {
5744887Schin job_wait((pid_t)0);
5754887Schin hist_eof(shp->hist_ptr);
5764887Schin sfsync(sfstderr);
5774887Schin }
5784887Schin if(sh_isoption(SH_HISTORY))
5794887Schin sh_onstate(SH_HISTORY);
5804887Schin job.waitall = job.curpgid = 0;
5814887Schin error_info.flags |= ERROR_INTERACTIVE;
5824887Schin t = (Shnode_t*)sh_parse(shp,iop,0);
5834887Schin if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_CFLAG))
5844887Schin error_info.flags &= ~ERROR_INTERACTIVE;
5854887Schin shp->readscript = 0;
5864887Schin if(sh_isstate(SH_INTERACTIVE) && shp->hist_ptr)
5874887Schin hist_flush(shp->hist_ptr);
5884887Schin sh_offstate(SH_HISTORY);
5894887Schin if(t)
5904887Schin {
5914887Schin execflags = sh_state(SH_ERREXIT)|sh_state(SH_INTERACTIVE);
5924887Schin /* The last command may not have to fork */
5934887Schin if(!sh_isstate(SH_PROFILE) && !sh_isstate(SH_INTERACTIVE) &&
5944887Schin (fno<0 || !(shp->fdstatus[fno]&(IOTTY|IONOSEEK)))
5954887Schin && !sfreserve(iop,0,0))
5964887Schin {
5974887Schin execflags |= sh_state(SH_NOFORK);
5984887Schin }
5994887Schin shp->st.execbrk = 0;
6004887Schin sh_exec(t,execflags);
6014887Schin if(shp->forked)
6024887Schin {
6034887Schin sh_offstate(SH_INTERACTIVE);
6044887Schin goto done;
6054887Schin }
6064887Schin /* This is for sh -t */
6074887Schin if(sh_isoption(SH_TFLAG) && !sh_isstate(SH_PROFILE))
6084887Schin tdone++;
6094887Schin }
6104887Schin }
6114887Schin done:
6124887Schin sh_popcontext(&buff);
6134887Schin if(sh_isstate(SH_INTERACTIVE))
6144887Schin {
6154887Schin sfputc(sfstderr,'\n');
6168462SApril.Chin@Sun.COM job_close(shp);
6174887Schin }
6184887Schin if(jmpval == SH_JMPSCRIPT)
6194887Schin siglongjmp(*shp->jmplist,jmpval);
6204887Schin else if(jmpval == SH_JMPEXIT)
6218462SApril.Chin@Sun.COM sh_done(shp,0);
6224887Schin if(fno>0)
6234887Schin sh_close(fno);
6244887Schin if(shp->st.filename)
6254887Schin free((void*)shp->st.filename);
6264887Schin shp->st.filename = 0;
6274887Schin }
6284887Schin
6294887Schin
6304887Schin /* prints out messages if files in list have been modified since last call */
chkmail(Shell_t * shp,char * files)6314887Schin static void chkmail(Shell_t *shp, char *files)
6324887Schin {
6334887Schin register char *cp,*sp,*qp;
6344887Schin register char save;
6354887Schin struct argnod *arglist=0;
6364887Schin int offset = staktell();
6374887Schin char *savstak=stakptr(0);
6384887Schin struct stat statb;
6394887Schin if(*(cp=files) == 0)
6404887Schin return;
6414887Schin sp = cp;
6424887Schin do
6434887Schin {
6444887Schin /* skip to : or end of string saving first '?' */
6454887Schin for(qp=0;*sp && *sp != ':';sp++)
6464887Schin if((*sp == '?' || *sp=='%') && qp == 0)
6474887Schin qp = sp;
6484887Schin save = *sp;
6494887Schin *sp = 0;
6504887Schin /* change '?' to end-of-string */
6514887Schin if(qp)
6524887Schin *qp = 0;
6534887Schin do
6544887Schin {
6554887Schin /* see if time has been modified since last checked
6564887Schin * and the access time <= the modification time
6574887Schin */
6584887Schin if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime
6594887Schin && statb.st_atime <= statb.st_mtime)
6604887Schin {
6614887Schin /* check for directory */
6624887Schin if(!arglist && S_ISDIR(statb.st_mode))
6634887Schin {
6644887Schin /* generate list of directory entries */
6654887Schin path_complete(cp,"/*",&arglist);
6664887Schin }
6674887Schin else
6684887Schin {
6694887Schin /*
6704887Schin * If the file has shrunk,
6714887Schin * or if the size is zero
6724887Schin * then don't print anything
6734887Schin */
6744887Schin if(statb.st_size &&
6754887Schin ( statb.st_ino != lastmail.st_ino
6764887Schin || statb.st_dev != lastmail.st_dev
6774887Schin || statb.st_size > lastmail.st_size))
6784887Schin {
6794887Schin /* save and restore $_ */
6804887Schin char *save = shp->lastarg;
6814887Schin shp->lastarg = cp;
6828462SApril.Chin@Sun.COM errormsg(SH_DICT,0,sh_mactry(shp,qp?qp+1:(char*)e_mailmsg));
6834887Schin shp->lastarg = save;
6844887Schin }
6854887Schin lastmail = statb;
6864887Schin break;
6874887Schin }
6884887Schin }
6894887Schin if(arglist)
6904887Schin {
6914887Schin cp = arglist->argval;
6924887Schin arglist = arglist->argchn.ap;
6934887Schin }
6944887Schin else
6954887Schin cp = 0;
6964887Schin }
6974887Schin while(cp);
6984887Schin if(qp)
6994887Schin *qp = '?';
7004887Schin *sp++ = save;
7014887Schin cp = sp;
7024887Schin }
7034887Schin while(save);
7044887Schin stakset(savstak,offset);
7054887Schin }
7064887Schin
7074887Schin #undef EXECARGS
7084887Schin #undef PSTAT
7094887Schin #if defined(_hdr_execargs) && defined(pdp11)
7104887Schin # include <execargs.h>
7114887Schin # define EXECARGS 1
7124887Schin #endif
7134887Schin
7144887Schin #if defined(_lib_pstat) && defined(_sys_pstat)
7154887Schin # include <sys/pstat.h>
7164887Schin # define PSTAT 1
7174887Schin #endif
7184887Schin
7194887Schin #if defined(_lib_fork) && !defined(_NEXT_SOURCE)
7204887Schin /*
7214887Schin * fix up command line for ps command
7224887Schin * mode is 0 for initialization
7234887Schin */
fixargs(char ** argv,int mode)7244887Schin static void fixargs(char **argv, int mode)
7254887Schin {
7264887Schin #if EXECARGS
7274887Schin *execargs=(char *)argv;
7284887Schin #else
7294887Schin static char *buff;
7304887Schin static int command_len;
7314887Schin register char *cp;
7324887Schin int offset=0,size;
7334887Schin # ifdef PSTAT
7344887Schin union pstun un;
7354887Schin if(mode==0)
7364887Schin {
7374887Schin struct pst_static st;
7384887Schin un.pst_static = &st;
7394887Schin if(pstat(PSTAT_STATIC, un, sizeof(struct pst_static), 1, 0)<0)
7404887Schin return;
7414887Schin command_len = st.command_length;
7424887Schin return;
7434887Schin }
7444887Schin stakseek(command_len+2);
7454887Schin buff = stakseek(0);
7464887Schin # else
7474887Schin if(mode==0)
7484887Schin {
7494887Schin buff = argv[0];
7504887Schin while(cp = *argv++)
7514887Schin command_len += strlen(cp)+1;
7524887Schin if(environ && *environ==buff+command_len)
7534887Schin {
7544887Schin for(argv=environ; cp = *argv; cp++)
7554887Schin {
7564887Schin if(command_len > CMD_LENGTH)
7574887Schin {
7584887Schin command_len = CMD_LENGTH;
7594887Schin break;
7604887Schin }
7614887Schin *argv++ = strdup(cp);
7624887Schin command_len += strlen(cp)+1;
7634887Schin }
7644887Schin }
7654887Schin command_len -= 1;
7664887Schin return;
7674887Schin }
7684887Schin # endif /* PSTAT */
7694887Schin if(command_len==0)
7704887Schin return;
7714887Schin while((cp = *argv++) && offset < command_len)
7724887Schin {
7734887Schin if(offset + (size=strlen(cp)) >= command_len)
7744887Schin size = command_len - offset;
7754887Schin memcpy(buff+offset,cp,size);
7764887Schin offset += size;
7774887Schin buff[offset++] = ' ';
7784887Schin }
7794887Schin buff[offset-1] = 0;
7804887Schin # ifdef PSTAT
7814887Schin un.pst_command = stakptr(0);
7824887Schin pstat(PSTAT_SETCMD,un,0,0,0);
7834887Schin # endif /* PSTAT */
7844887Schin #endif /* EXECARGS */
7854887Schin }
7864887Schin #endif /* _lib_fork */
787