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
clearsigmask(register int sig)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
sh_source(Shell_t * shp,Sfio_t * iop,const char * file)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
sh_main(int ac,char * av[],Shinit_f userinit)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
exfile(register Shell_t * shp,register Sfio_t * iop,register int fno)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 */
chkmail(Shell_t * shp,char * files)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 */
fixargs(char ** argv,int mode)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