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