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