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