date and time created 88/07/21 17:34:32 by marc
authorMarc Teitelbaum <marc@ucbvax.Berkeley.EDU>
Fri, 22 Jul 1988 08:34:32 +0000 (00:34 -0800)
committerMarc Teitelbaum <marc@ucbvax.Berkeley.EDU>
Fri, 22 Jul 1988 08:34:32 +0000 (00:34 -0800)
SCCS-vsn: local/toolchest/ksh/sh/vfork.c 1.1

usr/src/local/toolchest/ksh/sh/vfork.c [new file with mode: 0644]

diff --git a/usr/src/local/toolchest/ksh/sh/vfork.c b/usr/src/local/toolchest/ksh/sh/vfork.c
new file mode 100644 (file)
index 0000000..425d7a0
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+
+ *      Copyright (c) 1984, 1985, 1986 AT&T
+ *      All Rights Reserved
+
+ *      THIS IS UNPUBLISHED PROPRIETARY SOURCE 
+ *      CODE OF AT&T.
+ *      The copyright notice above does not 
+ *      evidence any actual or intended
+ *      publication of such source code.
+
+ */
+/* @(#)vfork.c 1.1 */
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten by David Korn
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "flags.h"
+#include       "defs.h"
+#include       "sym.h"
+#include       "name.h"
+#include       "io.h"
+#include       "stak.h"
+#include       "jobs.h"
+#include       "builtins.h"
+#include       "brkincr.h"
+#include       "mode.h"
+
+/*
+ * This module is provided to allow the Shell to work with vfork instead
+ * of fork.  With vfork the data area is shared by parent and child.
+ * Save state variables at fork and make Shell variables copy on write.
+ * Restore everything to previous state when fork_exit is called and
+ * terminate process.
+ */
+
+/* The following structure contains the variables that must be saved */
+struct f_save
+{
+       struct  f_save *f_save_fork;
+       DOLPTR  f_savearg;
+       STKPTR  f_staksave;
+       struct  State   f_st;
+       char    f_trapflg[MAXTRAP+1];
+       char    *f_trapcom[MAXTRAP+1];
+       FILE    f_save_iob[FCIO+1];
+       struct  jobs    f_jobstat;
+};
+
+/* The following routines are defined by this module */
+int    vfork_check();
+void   vfork_restore();
+int    vfork_save();
+
+/* The following external routines are referenced by this module */
+extern DOLPTR          arg_use();
+extern void            arg_free();
+extern NAMPTR          checkfor();
+extern unsigned                chkid();
+extern void            free();
+extern char            *malloc();
+extern struct Amemory  *namep;
+extern char            *simple();
+extern char            trapflg[];
+extern char            *valup();
+
+static struct f_save *save_fork;       /* most recently saved data */
+
+/*
+ * Save state on fork
+ */
+
+int    vfork_save()
+{
+       register struct f_save *fp = (struct f_save*)malloc(sizeof(struct f_save));
+       if(fp==NULL)
+               return(-1);
+       locstak();
+       fp->f_save_fork = save_fork;
+       save_fork = fp;
+       fp->f_staksave = savstak();
+       fp->f_st = st;
+       fp->f_jobstat = jobstat;
+       jobstat.p_pwlist = 0;
+       fp->f_savearg = arg_use();
+       bcopy(trapflg,fp->f_trapflg,MAXTRAP+1);
+       bcopy((char*)trapcom,(char*)fp->f_trapcom,(MAXTRAP+1)*sizeof(char*));
+#ifdef _N_STATIC_IOBS
+       bcopy((char*)_iob,(char*)fp->f_save_iob,(_N_STATIC_IOBS)*sizeof(FILE));
+       bcopy((char*)_myiob,(char*)(fp->f_save_iob+_N_STATIC_IOBS),
+               (FCIO+1-_N_STATIC_IOBS)*sizeof(FILE));
+#else
+       bcopy((char*)_iob,(char*)fp->f_save_iob,(FCIO+1)*sizeof(FILE));
+#endif /* _N_STATIC_IOBS */
+       states |= VFORKED;
+       return(0);
+}
+
+/*
+ * Restore state and exit
+ */
+
+void   vfork_restore()
+{
+       register struct f_save *fp = save_fork;
+       if((states&VFORKED)==0)
+               return;
+#ifdef _N_STATIC_IOBS
+       bcopy((char*)fp->f_save_iob,(char*)_iob,(_N_STATIC_IOBS)*sizeof(FILE));
+       bcopy((char*)(fp->f_save_iob+_N_STATIC_IOBS),(char*)_myiob,
+               (FCIO+1-_N_STATIC_IOBS)*sizeof(FILE));
+#else
+       bcopy((char*)fp->f_save_iob,(char*)_iob,(FCIO+1)*sizeof(FILE));
+#endif /* _N_STATIC_IOBS */
+       bcopy(fp->f_trapflg,trapflg,MAXTRAP+1);
+       bcopy((char*)fp->f_trapcom,(char*)trapcom,(MAXTRAP+1)*sizeof(char*));
+       st = fp->f_st;
+       jobstat = fp->f_jobstat;
+       arg_free(fp->f_savearg,0);
+       save_fork = fp->f_save_fork;
+       free(fp);
+       tdystak(fp->f_staksave);
+}
+
+
+/*
+ * Get the interpreter name given a script file 
+ * The first line must be of the form #!  <iname>.
+ * Returns 1 if <iname> is found, 0 otherwise
+ */
+int     get_shell(name,iname)
+char *name;
+char *iname;
+{
+       register int c;
+       register int state = 0;
+       register int fd;
+       int n;
+       char *cp;
+       int     rval = 0;
+       char buffer[256];
+       cp = valup(SHELLNOD);
+       /* don't use csh */
+       if(strcmp(simple(cp),"csh")==0)
+               cp = 0;
+       strcpy(iname,cp?cp:"/bin/sh");
+       if((fd=open(name,0))<0)
+               return(-1);
+       n = read(fd,buffer,sizeof(buffer));
+       cp = buffer;
+       while(n-- > 0)
+       {
+               c = *cp++;
+               switch(state)
+               {
+                       case 0:
+                               if(c!='#')
+                                       goto out;
+                               break;
+
+                       case 1:
+                               if(c!='!')
+                                       goto out;
+                               break;
+
+                       case 2:
+                               if(c==' ' || c =='\t')
+                                       continue;
+                       default:
+                               if(c=='\n')
+                               {
+                                       *iname = 0;
+                                       rval = 1;
+                                       goto out;
+                               }
+                               *iname++ = c;
+               }
+               state++;
+       }
+out:
+       close(fd);
+       return(rval);
+}
+
+/*
+ * returns non-zero if process should vfork, 0 otherwise
+ * we do not vfork for functions and built-ins in the background
+ */
+int    vfork_check(t)
+TREPTR t;
+{
+       register COMPTR tf;
+       register ARGPTR arg;
+       register char *arg0 = NIL;
+       NAMPTR np;
+       int bltno;
+       /* simple command */
+       if((t->tretyp&COMMSK)==TCOM)
+               return(1);
+       tf = (COMPTR)(((FORKPTR)t)->forktre);
+       if((tf->comtyp&COMMSK)!=TCOM)
+               return(0);
+       /* background command */
+       arg = tf->comarg;
+       bltno = tf->comtyp>>(COMBITS+1);
+       /* can't vfork assignments or most built-ins */
+       if(arg==0 || bltno > SYSLOGIN)
+               return(0);
+       if(tf->comtyp&COMSCAN)
+       {
+               if(arg->argflag&A_RAW)
+                       arg0 = arg->argval;
+       }
+       else
+               arg0 = *(((DOLPTR)arg)->dolarg+1);
+       /* no vfork if not sure */
+       if(arg0==NIL)
+               return(0);
+       /* eliminate functions */
+       if(chkid(arg0) && (np=checkfor(arg0,prnames))&&  np->value.namval.ip)
+               return(0);
+       /* command substitution with i/o redirection use fork */
+       if((t->tretyp&FCOMSUB) && t->treio==(IOPTR)0)
+               return(0);
+       return(2);
+}
+
+#ifndef BSD_4_2
+/*
+ * copy <n> bytes from <sp> to <dp>
+ */ 
+
+int bcopy(sp,dp,n)
+register char *sp, *dp;
+register int n;
+{
+       while(n-- >0)
+               *dp++ = *sp++;
+}
+#endif BSD_4_2