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