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