/* char *startchild_defgb(name,cin,cout) char *name; FILE **cin, **cout; name: procedure name (either in search path or full path specified) cin: pointer to place into which startchild returns the stream pointer to opened file which will be child's stdin. If NULL, nothing opened or returned cout: same as cin, but for child's stdout In parent context, returns NULL if things worked; pointer to (dynamically allocated) error string otherwise. In child context, we have new process if things worked; a message to stdout and an exit w/non-zero status (errno if non-0; 1 else-too bad if errno=1!) otherwise. */ char startchild_id[]="startchild_defgb version 1.2 27 Jan 99"; /* 27 Jan 99. Avoid opening & returning streams if they are given as NULL Test more (hopefully all!) system calls Return a pointer to an error string instead of errno. [Begin 1.2] 25 Jan 99. Return errno in case of parent error instead of exiting. Rename startchild startchild_defgb to reflect this calling sequence change. WJS [Begin 1.1] 15 May 98. Type startchild so compiler is happy 26 Apr 97. Change error string to match JGOFS protocol. WJS 14 Mar 97. Write in 1 printf instead of 2 (got first line but not 2nd-hope this helps & doesn't eliminate both instead!) Exit w/errno instead of 1 if errno non-zero. WJS 3 Jun 96. Change error string so defgb can recognize it as error. WJS 30 May 96. Mod to child process behavior after failed exec. WJS 1) print error info to stdout instead of stderr and flush it, thus feeding message to parent 2) _exit() [Original source startchild.c from defexec stuff, I think] */ #include #include #include #if SOL || HP #include #include #endif int errno_sav; void child_error(s,image) char *s,*image; { /* "&x" is magic string causing defgb to interpret line as error */ /* message. Defined as ERR_PREFIX in defgb.h, but not sure I */ /* should include that in what is possibly a library subroutine */ printf("&x startchild_defgb %s error in child process\n%s: %s\n", s,image,strerror(errno)); fflush(NULL); if (errno == 0) errno = 1; _exit(errno); } char *parent_error(s) char *s; { static char *err_string; char *err_ptr; char *msg = ". errno msg: "; int len_s,len_msg; err_ptr = (errno > 0) ? strerror(errno) : "[None-errno not set]"; len_s = strlen(s); len_msg = strlen(msg); if ( (err_string = (char *)malloc(len_s + len_msg + strlen(err_ptr) + 1)) == NULL ) { err_string = (errno > 0) ? err_ptr : s; errno = errno_sav; return err_string; } strcpy (err_string,s); strcpy (err_string+len_s,msg); strcpy (err_string+len_s+len_msg,err_ptr); errno = errno_sav; return err_string; } char *startchild_defgb(name,cin,cout) char *name; FILE **cin, **cout; { static int pipeto[2],pipefrom[2]; int i,j,numfds,childpid; char *args[20]; #if SOL || HP struct rlimit rlp; #endif errno_sav = errno; errno = -1; /* Set to a know value in case functions don't set it */ if (pipe(pipeto) || pipe(pipefrom) <0) return parent_error("pipe problem"); switch (childpid = fork()) { case -1: /* fork error */ return parent_error("Could not fork"); case 0: /* child process */ /* Break up input string into argument vector */ i = 0; args[i++] = strtok(name," "); while ( (args[i]=strtok(NULL," ")) != NULL ) i++; /* fprintf(stderr,"got here after fork\n"); fprintf(stderr,"%s\n",name); */ if (dup2(pipeto[0],0) < 0) child_error("dup2-pipeto",args[0]); if (dup2(pipefrom[1],1) < 0) child_error("dup2-pipefrom",args[0]); /* Close all open files except stdin, stdout, and stderr. Do */ /* this by trying to close every legal file descriptor >= 3, */ /* ignoring BADF, which means that particular descriptor was */ /* not pointing to an open file (? or is otherwise illegal) */ #if SOL || HP if (getrlimit(RLIMIT_NOFILE,&rlp) != 0) child_error("getrlimit",args[0]); numfds = rlp.rlim_cur; #else numfds = getdtablesize(); #endif for (i=3; i