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