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