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 */
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
clearsigmask(register int sig)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
sh_source(Shell_t * shp,Sfio_t * iop,const char * file)94 int 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
sh_main(int ac,char * av[],Shinit_f userinit)121 int 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
exfile(register Shell_t * shp,register Sfio_t * iop,register int fno)364 static 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 }
592 done:
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 */
chkmail(Shell_t * shp,char * files)612 static 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 */
fixargs(char ** argv,int mode)705 static 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