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