1*f65c41c7Smarc /*
2*f65c41c7Smarc
3*f65c41c7Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*f65c41c7Smarc * All Rights Reserved
5*f65c41c7Smarc
6*f65c41c7Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*f65c41c7Smarc * CODE OF AT&T.
8*f65c41c7Smarc * The copyright notice above does not
9*f65c41c7Smarc * evidence any actual or intended
10*f65c41c7Smarc * publication of such source code.
11*f65c41c7Smarc
12*f65c41c7Smarc */
13*f65c41c7Smarc /* @(#)vfork.c 1.1 */
14*f65c41c7Smarc /*
15*f65c41c7Smarc * UNIX shell
16*f65c41c7Smarc *
17*f65c41c7Smarc * S. R. Bourne
18*f65c41c7Smarc * Rewritten by David Korn
19*f65c41c7Smarc * Bell Telephone Laboratories
20*f65c41c7Smarc *
21*f65c41c7Smarc */
22*f65c41c7Smarc
23*f65c41c7Smarc #include "flags.h"
24*f65c41c7Smarc #include "defs.h"
25*f65c41c7Smarc #include "sym.h"
26*f65c41c7Smarc #include "name.h"
27*f65c41c7Smarc #include "io.h"
28*f65c41c7Smarc #include "stak.h"
29*f65c41c7Smarc #include "jobs.h"
30*f65c41c7Smarc #include "builtins.h"
31*f65c41c7Smarc #include "brkincr.h"
32*f65c41c7Smarc #include "mode.h"
33*f65c41c7Smarc
34*f65c41c7Smarc /*
35*f65c41c7Smarc * This module is provided to allow the Shell to work with vfork instead
36*f65c41c7Smarc * of fork. With vfork the data area is shared by parent and child.
37*f65c41c7Smarc * Save state variables at fork and make Shell variables copy on write.
38*f65c41c7Smarc * Restore everything to previous state when fork_exit is called and
39*f65c41c7Smarc * terminate process.
40*f65c41c7Smarc */
41*f65c41c7Smarc
42*f65c41c7Smarc /* The following structure contains the variables that must be saved */
43*f65c41c7Smarc struct f_save
44*f65c41c7Smarc {
45*f65c41c7Smarc struct f_save *f_save_fork;
46*f65c41c7Smarc DOLPTR f_savearg;
47*f65c41c7Smarc STKPTR f_staksave;
48*f65c41c7Smarc struct State f_st;
49*f65c41c7Smarc char f_trapflg[MAXTRAP+1];
50*f65c41c7Smarc char *f_trapcom[MAXTRAP+1];
51*f65c41c7Smarc FILE f_save_iob[FCIO+1];
52*f65c41c7Smarc struct jobs f_jobstat;
53*f65c41c7Smarc };
54*f65c41c7Smarc
55*f65c41c7Smarc /* The following routines are defined by this module */
56*f65c41c7Smarc int vfork_check();
57*f65c41c7Smarc void vfork_restore();
58*f65c41c7Smarc int vfork_save();
59*f65c41c7Smarc
60*f65c41c7Smarc /* The following external routines are referenced by this module */
61*f65c41c7Smarc extern DOLPTR arg_use();
62*f65c41c7Smarc extern void arg_free();
63*f65c41c7Smarc extern NAMPTR checkfor();
64*f65c41c7Smarc extern unsigned chkid();
65*f65c41c7Smarc extern void free();
66*f65c41c7Smarc extern char *malloc();
67*f65c41c7Smarc extern struct Amemory *namep;
68*f65c41c7Smarc extern char *simple();
69*f65c41c7Smarc extern char trapflg[];
70*f65c41c7Smarc extern char *valup();
71*f65c41c7Smarc
72*f65c41c7Smarc static struct f_save *save_fork; /* most recently saved data */
73*f65c41c7Smarc
74*f65c41c7Smarc /*
75*f65c41c7Smarc * Save state on fork
76*f65c41c7Smarc */
77*f65c41c7Smarc
vfork_save()78*f65c41c7Smarc int vfork_save()
79*f65c41c7Smarc {
80*f65c41c7Smarc register struct f_save *fp = (struct f_save*)malloc(sizeof(struct f_save));
81*f65c41c7Smarc if(fp==NULL)
82*f65c41c7Smarc return(-1);
83*f65c41c7Smarc locstak();
84*f65c41c7Smarc fp->f_save_fork = save_fork;
85*f65c41c7Smarc save_fork = fp;
86*f65c41c7Smarc fp->f_staksave = savstak();
87*f65c41c7Smarc fp->f_st = st;
88*f65c41c7Smarc fp->f_jobstat = jobstat;
89*f65c41c7Smarc jobstat.p_pwlist = 0;
90*f65c41c7Smarc fp->f_savearg = arg_use();
91*f65c41c7Smarc bcopy(trapflg,fp->f_trapflg,MAXTRAP+1);
92*f65c41c7Smarc bcopy((char*)trapcom,(char*)fp->f_trapcom,(MAXTRAP+1)*sizeof(char*));
93*f65c41c7Smarc #ifdef _N_STATIC_IOBS
94*f65c41c7Smarc bcopy((char*)_iob,(char*)fp->f_save_iob,(_N_STATIC_IOBS)*sizeof(FILE));
95*f65c41c7Smarc bcopy((char*)_myiob,(char*)(fp->f_save_iob+_N_STATIC_IOBS),
96*f65c41c7Smarc (FCIO+1-_N_STATIC_IOBS)*sizeof(FILE));
97*f65c41c7Smarc #else
98*f65c41c7Smarc bcopy((char*)_iob,(char*)fp->f_save_iob,(FCIO+1)*sizeof(FILE));
99*f65c41c7Smarc #endif /* _N_STATIC_IOBS */
100*f65c41c7Smarc states |= VFORKED;
101*f65c41c7Smarc return(0);
102*f65c41c7Smarc }
103*f65c41c7Smarc
104*f65c41c7Smarc /*
105*f65c41c7Smarc * Restore state and exit
106*f65c41c7Smarc */
107*f65c41c7Smarc
vfork_restore()108*f65c41c7Smarc void vfork_restore()
109*f65c41c7Smarc {
110*f65c41c7Smarc register struct f_save *fp = save_fork;
111*f65c41c7Smarc if((states&VFORKED)==0)
112*f65c41c7Smarc return;
113*f65c41c7Smarc #ifdef _N_STATIC_IOBS
114*f65c41c7Smarc bcopy((char*)fp->f_save_iob,(char*)_iob,(_N_STATIC_IOBS)*sizeof(FILE));
115*f65c41c7Smarc bcopy((char*)(fp->f_save_iob+_N_STATIC_IOBS),(char*)_myiob,
116*f65c41c7Smarc (FCIO+1-_N_STATIC_IOBS)*sizeof(FILE));
117*f65c41c7Smarc #else
118*f65c41c7Smarc bcopy((char*)fp->f_save_iob,(char*)_iob,(FCIO+1)*sizeof(FILE));
119*f65c41c7Smarc #endif /* _N_STATIC_IOBS */
120*f65c41c7Smarc bcopy(fp->f_trapflg,trapflg,MAXTRAP+1);
121*f65c41c7Smarc bcopy((char*)fp->f_trapcom,(char*)trapcom,(MAXTRAP+1)*sizeof(char*));
122*f65c41c7Smarc st = fp->f_st;
123*f65c41c7Smarc jobstat = fp->f_jobstat;
124*f65c41c7Smarc arg_free(fp->f_savearg,0);
125*f65c41c7Smarc save_fork = fp->f_save_fork;
126*f65c41c7Smarc free(fp);
127*f65c41c7Smarc tdystak(fp->f_staksave);
128*f65c41c7Smarc }
129*f65c41c7Smarc
130*f65c41c7Smarc
131*f65c41c7Smarc /*
132*f65c41c7Smarc * Get the interpreter name given a script file
133*f65c41c7Smarc * The first line must be of the form #! <iname>.
134*f65c41c7Smarc * Returns 1 if <iname> is found, 0 otherwise
135*f65c41c7Smarc */
get_shell(name,iname)136*f65c41c7Smarc int get_shell(name,iname)
137*f65c41c7Smarc char *name;
138*f65c41c7Smarc char *iname;
139*f65c41c7Smarc {
140*f65c41c7Smarc register int c;
141*f65c41c7Smarc register int state = 0;
142*f65c41c7Smarc register int fd;
143*f65c41c7Smarc int n;
144*f65c41c7Smarc char *cp;
145*f65c41c7Smarc int rval = 0;
146*f65c41c7Smarc char buffer[256];
147*f65c41c7Smarc cp = valup(SHELLNOD);
148*f65c41c7Smarc /* don't use csh */
149*f65c41c7Smarc if(strcmp(simple(cp),"csh")==0)
150*f65c41c7Smarc cp = 0;
151*f65c41c7Smarc strcpy(iname,cp?cp:"/bin/sh");
152*f65c41c7Smarc if((fd=open(name,0))<0)
153*f65c41c7Smarc return(-1);
154*f65c41c7Smarc n = read(fd,buffer,sizeof(buffer));
155*f65c41c7Smarc cp = buffer;
156*f65c41c7Smarc while(n-- > 0)
157*f65c41c7Smarc {
158*f65c41c7Smarc c = *cp++;
159*f65c41c7Smarc switch(state)
160*f65c41c7Smarc {
161*f65c41c7Smarc case 0:
162*f65c41c7Smarc if(c!='#')
163*f65c41c7Smarc goto out;
164*f65c41c7Smarc break;
165*f65c41c7Smarc
166*f65c41c7Smarc case 1:
167*f65c41c7Smarc if(c!='!')
168*f65c41c7Smarc goto out;
169*f65c41c7Smarc break;
170*f65c41c7Smarc
171*f65c41c7Smarc case 2:
172*f65c41c7Smarc if(c==' ' || c =='\t')
173*f65c41c7Smarc continue;
174*f65c41c7Smarc default:
175*f65c41c7Smarc if(c=='\n')
176*f65c41c7Smarc {
177*f65c41c7Smarc *iname = 0;
178*f65c41c7Smarc rval = 1;
179*f65c41c7Smarc goto out;
180*f65c41c7Smarc }
181*f65c41c7Smarc *iname++ = c;
182*f65c41c7Smarc }
183*f65c41c7Smarc state++;
184*f65c41c7Smarc }
185*f65c41c7Smarc out:
186*f65c41c7Smarc close(fd);
187*f65c41c7Smarc return(rval);
188*f65c41c7Smarc }
189*f65c41c7Smarc
190*f65c41c7Smarc /*
191*f65c41c7Smarc * returns non-zero if process should vfork, 0 otherwise
192*f65c41c7Smarc * we do not vfork for functions and built-ins in the background
193*f65c41c7Smarc */
vfork_check(t)194*f65c41c7Smarc int vfork_check(t)
195*f65c41c7Smarc TREPTR t;
196*f65c41c7Smarc {
197*f65c41c7Smarc register COMPTR tf;
198*f65c41c7Smarc register ARGPTR arg;
199*f65c41c7Smarc register char *arg0 = NIL;
200*f65c41c7Smarc NAMPTR np;
201*f65c41c7Smarc int bltno;
202*f65c41c7Smarc /* simple command */
203*f65c41c7Smarc if((t->tretyp&COMMSK)==TCOM)
204*f65c41c7Smarc return(1);
205*f65c41c7Smarc tf = (COMPTR)(((FORKPTR)t)->forktre);
206*f65c41c7Smarc if((tf->comtyp&COMMSK)!=TCOM)
207*f65c41c7Smarc return(0);
208*f65c41c7Smarc /* background command */
209*f65c41c7Smarc arg = tf->comarg;
210*f65c41c7Smarc bltno = tf->comtyp>>(COMBITS+1);
211*f65c41c7Smarc /* can't vfork assignments or most built-ins */
212*f65c41c7Smarc if(arg==0 || bltno > SYSLOGIN)
213*f65c41c7Smarc return(0);
214*f65c41c7Smarc if(tf->comtyp&COMSCAN)
215*f65c41c7Smarc {
216*f65c41c7Smarc if(arg->argflag&A_RAW)
217*f65c41c7Smarc arg0 = arg->argval;
218*f65c41c7Smarc }
219*f65c41c7Smarc else
220*f65c41c7Smarc arg0 = *(((DOLPTR)arg)->dolarg+1);
221*f65c41c7Smarc /* no vfork if not sure */
222*f65c41c7Smarc if(arg0==NIL)
223*f65c41c7Smarc return(0);
224*f65c41c7Smarc /* eliminate functions */
225*f65c41c7Smarc if(chkid(arg0) && (np=checkfor(arg0,prnames))&& np->value.namval.ip)
226*f65c41c7Smarc return(0);
227*f65c41c7Smarc /* command substitution with i/o redirection use fork */
228*f65c41c7Smarc if((t->tretyp&FCOMSUB) && t->treio==(IOPTR)0)
229*f65c41c7Smarc return(0);
230*f65c41c7Smarc return(2);
231*f65c41c7Smarc }
232*f65c41c7Smarc
233*f65c41c7Smarc #ifndef BSD_4_2
234*f65c41c7Smarc /*
235*f65c41c7Smarc * copy <n> bytes from <sp> to <dp>
236*f65c41c7Smarc */
237*f65c41c7Smarc
bcopy(sp,dp,n)238*f65c41c7Smarc int bcopy(sp,dp,n)
239*f65c41c7Smarc register char *sp, *dp;
240*f65c41c7Smarc register int n;
241*f65c41c7Smarc {
242*f65c41c7Smarc while(n-- >0)
243*f65c41c7Smarc *dp++ = *sp++;
244*f65c41c7Smarc }
245*f65c41c7Smarc #endif BSD_4_2
246