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