xref: /original-bsd/local/toolchest/ksh/sh/vfork.c (revision f1324ba5)
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 
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 
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  */
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  */
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 
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