14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1982-2009 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" 40*10898Sroland.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 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 */ 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 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) 118*10898Sroland.mainz@nrubsig.org { 119*10898Sroland.mainz@nrubsig.org REGRESS(source, "sh_source", ("%s:ENOENT", file)); 1204887Schin return 0; 121*10898Sroland.mainz@nrubsig.org } 1224887Schin oid = error_info.id; 1234887Schin nid = error_info.id = strdup(file); 1244887Schin shp->st.filename = path_fullname(stakptr(PATH_OFFSET)); 125*10898Sroland.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 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); 185*10898Sroland.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 { 283*10898Sroland.mainz@nrubsig.org #if !_WINIX 2844887Schin char *cp; 2854887Schin int type; 286*10898Sroland.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 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)) 4464887Schin goto done; 4478462SApril.Chin@Sun.COM if(!sh_isoption(SH_INTERACTIVE) || sh_isstate(SH_FORKED) || (jmpval > SH_JMPERREXIT && job_close(shp) >=0)) 4484887Schin { 4494887Schin sh_offstate(SH_INTERACTIVE); 4504887Schin sh_offstate(SH_MONITOR); 4514887Schin goto done; 4524887Schin } 4534887Schin /* skip over remaining input */ 4544887Schin if(top = fcfile()) 4554887Schin { 4564887Schin while(fcget()>0); 4574887Schin fcclose(); 4584887Schin while(top=sfstack(iop,SF_POPSTACK)) 4594887Schin sfclose(top); 4604887Schin } 4614887Schin /* make sure that we own the terminal */ 4624887Schin #ifdef SIGTSTP 4634887Schin tcsetpgrp(job.fd,shp->pid); 4644887Schin #endif /* SIGTSTP */ 4654887Schin } 4664887Schin /* error return here */ 4674887Schin sfclrerr(iop); 4684887Schin sh_setstate(states); 4694887Schin shp->st.optindex = 1; 4704887Schin opt_info.offset = 0; 4714887Schin shp->st.loopcnt = 0; 4724887Schin shp->trapnote = 0; 4734887Schin shp->intrap = 0; 4744887Schin error_info.line = 1; 4754887Schin shp->inlineno = 1; 4764887Schin shp->binscript = 0; 4774887Schin if(sfeof(iop)) 4784887Schin goto eof_or_error; 4794887Schin /* command loop */ 4804887Schin while(1) 4814887Schin { 4824887Schin shp->nextprompt = 1; 4838462SApril.Chin@Sun.COM sh_freeup(shp); 4844887Schin stakset(NIL(char*),0); 4854887Schin exitset(); 4864887Schin sh_offstate(SH_STOPOK); 4874887Schin sh_offstate(SH_ERREXIT); 4884887Schin sh_offstate(SH_VERBOSE); 4894887Schin sh_offstate(SH_TIMING); 4904887Schin sh_offstate(SH_GRACE); 4914887Schin sh_offstate(SH_TTYWAIT); 4924887Schin if(sh_isoption(SH_VERBOSE)) 4934887Schin sh_onstate(SH_VERBOSE); 4944887Schin sh_onstate(SH_ERREXIT); 4954887Schin /* -eim flags don't apply to profiles */ 4964887Schin if(sh_isstate(SH_PROFILE)) 4974887Schin { 4984887Schin sh_offstate(SH_INTERACTIVE); 4994887Schin sh_offstate(SH_ERREXIT); 5004887Schin sh_offstate(SH_MONITOR); 5014887Schin } 5024887Schin if(sh_isstate(SH_INTERACTIVE) && !tdone) 5034887Schin { 5044887Schin register char *mail; 5054887Schin #ifdef JOBS 5064887Schin sh_offstate(SH_MONITOR); 5074887Schin if(sh_isoption(SH_MONITOR)) 5084887Schin sh_onstate(SH_MONITOR); 5094887Schin if(job.pwlist) 5104887Schin { 5114887Schin job_walk(sfstderr,job_list,JOB_NFLAG,(char**)0); 5124887Schin job_wait((pid_t)0); 5134887Schin } 5144887Schin #endif /* JOBS */ 5154887Schin if((mail=nv_getval(MAILPNOD)) || (mail=nv_getval(MAILNOD))) 5164887Schin { 5174887Schin time(&curtime); 5184887Schin if ((curtime - mailtime) >= sh_mailchk) 5194887Schin { 5204887Schin chkmail(shp,mail); 5214887Schin mailtime = curtime; 5224887Schin } 5234887Schin } 5244887Schin if(shp->hist_ptr) 5254887Schin hist_eof(shp->hist_ptr); 5264887Schin /* sets timeout for command entry */ 5274887Schin shp->timeout = shp->st.tmout; 5284887Schin #if SHOPT_TIMEOUT 5294887Schin if(shp->timeout <= 0 || shp->timeout > SHOPT_TIMEOUT) 5304887Schin shp->timeout = SHOPT_TIMEOUT; 5314887Schin #endif /* SHOPT_TIMEOUT */ 5324887Schin shp->inlineno = 1; 5334887Schin error_info.line = 1; 5344887Schin shp->exitval = 0; 5354887Schin shp->trapnote = 0; 5364887Schin if(buff.mode == SH_JMPEXIT) 5374887Schin { 5384887Schin buff.mode = SH_JMPERREXIT; 5394887Schin #ifdef DEBUG 5404887Schin errormsg(SH_DICT,ERROR_warn(0),"%d: mode changed to JMP_EXIT",getpid()); 5414887Schin #endif 5424887Schin } 5434887Schin } 5444887Schin errno = 0; 5454887Schin if(tdone || !sfreserve(iop,0,0)) 5464887Schin { 5474887Schin eof_or_error: 5484887Schin if(sh_isstate(SH_INTERACTIVE) && !sferror(iop)) 5494887Schin { 5504887Schin if(--maxtry>0 && sh_isoption(SH_IGNOREEOF) && 5514887Schin !sferror(sfstderr) && (shp->fdstatus[fno]&IOTTY)) 5524887Schin { 5534887Schin sfclrerr(iop); 5544887Schin errormsg(SH_DICT,0,e_logout); 5554887Schin continue; 5564887Schin } 5578462SApril.Chin@Sun.COM else if(job_close(shp)<0) 5584887Schin continue; 5594887Schin } 5604887Schin if(errno==0 && sferror(iop) && --maxtry>0) 5614887Schin { 5624887Schin sfclrlock(iop); 5634887Schin sfclrerr(iop); 5644887Schin continue; 5654887Schin } 5664887Schin goto done; 5674887Schin } 5684887Schin maxtry = IOMAXTRY; 5694887Schin if(sh_isstate(SH_INTERACTIVE) && shp->hist_ptr) 5704887Schin { 5714887Schin job_wait((pid_t)0); 5724887Schin hist_eof(shp->hist_ptr); 5734887Schin sfsync(sfstderr); 5744887Schin } 5754887Schin if(sh_isoption(SH_HISTORY)) 5764887Schin sh_onstate(SH_HISTORY); 5774887Schin job.waitall = job.curpgid = 0; 5784887Schin error_info.flags |= ERROR_INTERACTIVE; 5794887Schin t = (Shnode_t*)sh_parse(shp,iop,0); 5804887Schin if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_CFLAG)) 5814887Schin error_info.flags &= ~ERROR_INTERACTIVE; 5824887Schin shp->readscript = 0; 5834887Schin if(sh_isstate(SH_INTERACTIVE) && shp->hist_ptr) 5844887Schin hist_flush(shp->hist_ptr); 5854887Schin sh_offstate(SH_HISTORY); 5864887Schin if(t) 5874887Schin { 5884887Schin execflags = sh_state(SH_ERREXIT)|sh_state(SH_INTERACTIVE); 5894887Schin /* The last command may not have to fork */ 5904887Schin if(!sh_isstate(SH_PROFILE) && !sh_isstate(SH_INTERACTIVE) && 5914887Schin (fno<0 || !(shp->fdstatus[fno]&(IOTTY|IONOSEEK))) 5924887Schin && !sfreserve(iop,0,0)) 5934887Schin { 5944887Schin execflags |= sh_state(SH_NOFORK); 5954887Schin } 5964887Schin shp->st.execbrk = 0; 5974887Schin sh_exec(t,execflags); 5984887Schin if(shp->forked) 5994887Schin { 6004887Schin sh_offstate(SH_INTERACTIVE); 6014887Schin goto done; 6024887Schin } 6034887Schin /* This is for sh -t */ 6044887Schin if(sh_isoption(SH_TFLAG) && !sh_isstate(SH_PROFILE)) 6054887Schin tdone++; 6064887Schin } 6074887Schin } 6084887Schin done: 6094887Schin sh_popcontext(&buff); 6104887Schin if(sh_isstate(SH_INTERACTIVE)) 6114887Schin { 6124887Schin sfputc(sfstderr,'\n'); 6138462SApril.Chin@Sun.COM job_close(shp); 6144887Schin } 6154887Schin if(jmpval == SH_JMPSCRIPT) 6164887Schin siglongjmp(*shp->jmplist,jmpval); 6174887Schin else if(jmpval == SH_JMPEXIT) 6188462SApril.Chin@Sun.COM sh_done(shp,0); 6194887Schin if(fno>0) 6204887Schin sh_close(fno); 6214887Schin if(shp->st.filename) 6224887Schin free((void*)shp->st.filename); 6234887Schin shp->st.filename = 0; 6244887Schin } 6254887Schin 6264887Schin 6274887Schin /* prints out messages if files in list have been modified since last call */ 6284887Schin static void chkmail(Shell_t *shp, char *files) 6294887Schin { 6304887Schin register char *cp,*sp,*qp; 6314887Schin register char save; 6324887Schin struct argnod *arglist=0; 6334887Schin int offset = staktell(); 6344887Schin char *savstak=stakptr(0); 6354887Schin struct stat statb; 6364887Schin if(*(cp=files) == 0) 6374887Schin return; 6384887Schin sp = cp; 6394887Schin do 6404887Schin { 6414887Schin /* skip to : or end of string saving first '?' */ 6424887Schin for(qp=0;*sp && *sp != ':';sp++) 6434887Schin if((*sp == '?' || *sp=='%') && qp == 0) 6444887Schin qp = sp; 6454887Schin save = *sp; 6464887Schin *sp = 0; 6474887Schin /* change '?' to end-of-string */ 6484887Schin if(qp) 6494887Schin *qp = 0; 6504887Schin do 6514887Schin { 6524887Schin /* see if time has been modified since last checked 6534887Schin * and the access time <= the modification time 6544887Schin */ 6554887Schin if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime 6564887Schin && statb.st_atime <= statb.st_mtime) 6574887Schin { 6584887Schin /* check for directory */ 6594887Schin if(!arglist && S_ISDIR(statb.st_mode)) 6604887Schin { 6614887Schin /* generate list of directory entries */ 6624887Schin path_complete(cp,"/*",&arglist); 6634887Schin } 6644887Schin else 6654887Schin { 6664887Schin /* 6674887Schin * If the file has shrunk, 6684887Schin * or if the size is zero 6694887Schin * then don't print anything 6704887Schin */ 6714887Schin if(statb.st_size && 6724887Schin ( statb.st_ino != lastmail.st_ino 6734887Schin || statb.st_dev != lastmail.st_dev 6744887Schin || statb.st_size > lastmail.st_size)) 6754887Schin { 6764887Schin /* save and restore $_ */ 6774887Schin char *save = shp->lastarg; 6784887Schin shp->lastarg = cp; 6798462SApril.Chin@Sun.COM errormsg(SH_DICT,0,sh_mactry(shp,qp?qp+1:(char*)e_mailmsg)); 6804887Schin shp->lastarg = save; 6814887Schin } 6824887Schin lastmail = statb; 6834887Schin break; 6844887Schin } 6854887Schin } 6864887Schin if(arglist) 6874887Schin { 6884887Schin cp = arglist->argval; 6894887Schin arglist = arglist->argchn.ap; 6904887Schin } 6914887Schin else 6924887Schin cp = 0; 6934887Schin } 6944887Schin while(cp); 6954887Schin if(qp) 6964887Schin *qp = '?'; 6974887Schin *sp++ = save; 6984887Schin cp = sp; 6994887Schin } 7004887Schin while(save); 7014887Schin stakset(savstak,offset); 7024887Schin } 7034887Schin 7044887Schin #undef EXECARGS 7054887Schin #undef PSTAT 7064887Schin #if defined(_hdr_execargs) && defined(pdp11) 7074887Schin # include <execargs.h> 7084887Schin # define EXECARGS 1 7094887Schin #endif 7104887Schin 7114887Schin #if defined(_lib_pstat) && defined(_sys_pstat) 7124887Schin # include <sys/pstat.h> 7134887Schin # define PSTAT 1 7144887Schin #endif 7154887Schin 7164887Schin #if defined(_lib_fork) && !defined(_NEXT_SOURCE) 7174887Schin /* 7184887Schin * fix up command line for ps command 7194887Schin * mode is 0 for initialization 7204887Schin */ 7214887Schin static void fixargs(char **argv, int mode) 7224887Schin { 7234887Schin #if EXECARGS 7244887Schin *execargs=(char *)argv; 7254887Schin #else 7264887Schin static char *buff; 7274887Schin static int command_len; 7284887Schin register char *cp; 7294887Schin int offset=0,size; 7304887Schin # ifdef PSTAT 7314887Schin union pstun un; 7324887Schin if(mode==0) 7334887Schin { 7344887Schin struct pst_static st; 7354887Schin un.pst_static = &st; 7364887Schin if(pstat(PSTAT_STATIC, un, sizeof(struct pst_static), 1, 0)<0) 7374887Schin return; 7384887Schin command_len = st.command_length; 7394887Schin return; 7404887Schin } 7414887Schin stakseek(command_len+2); 7424887Schin buff = stakseek(0); 7434887Schin # else 7444887Schin if(mode==0) 7454887Schin { 7464887Schin buff = argv[0]; 7474887Schin while(cp = *argv++) 7484887Schin command_len += strlen(cp)+1; 7494887Schin if(environ && *environ==buff+command_len) 7504887Schin { 7514887Schin for(argv=environ; cp = *argv; cp++) 7524887Schin { 7534887Schin if(command_len > CMD_LENGTH) 7544887Schin { 7554887Schin command_len = CMD_LENGTH; 7564887Schin break; 7574887Schin } 7584887Schin *argv++ = strdup(cp); 7594887Schin command_len += strlen(cp)+1; 7604887Schin } 7614887Schin } 7624887Schin command_len -= 1; 7634887Schin return; 7644887Schin } 7654887Schin # endif /* PSTAT */ 7664887Schin if(command_len==0) 7674887Schin return; 7684887Schin while((cp = *argv++) && offset < command_len) 7694887Schin { 7704887Schin if(offset + (size=strlen(cp)) >= command_len) 7714887Schin size = command_len - offset; 7724887Schin memcpy(buff+offset,cp,size); 7734887Schin offset += size; 7744887Schin buff[offset++] = ' '; 7754887Schin } 7764887Schin buff[offset-1] = 0; 7774887Schin # ifdef PSTAT 7784887Schin un.pst_command = stakptr(0); 7794887Schin pstat(PSTAT_SETCMD,un,0,0,0); 7804887Schin # endif /* PSTAT */ 7814887Schin #endif /* EXECARGS */ 7824887Schin } 7834887Schin #endif /* _lib_fork */ 784