/* char *startchild(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. */ #define STARTCHILD_ID "startchild version 1.2a 23 Apr 2004" /* 23 Apr 04. Mods to "version-returning function". a) change from local to global to ensure it can't be "optimized out" b) don't want "version" in any function name since such names appear when grep'ping for "version" 20 Feb 04. 4 digit year in ID string. Include .h file version in id 11 Feb 04. Change name; entries back to startchild Get &x defn from core.h. Might also fix some compiler warnings [Begin 1.2a] 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 "core.h" /* Next set of defns seem to be "system" related. In particular, */ /* time.h and sys/time.h seem to be different beasts, w/the latter */ /* relevant only here (and hence it should NOT be in core.h) */ /* (Hmm... also seems to be in jdb.c... who knows?) */ #if SOL || HP #include #include #endif int errno_sav; /************************************************************************/ char *startchild_return_vers() /* Dummy routine. Exists only to force .h file version string into */ /* this module. Note string must not be global or we'll have con- */ /* flicts if another routine similarly includes the version string */ { static char version[] = STARTCHILD_ID"/"COREH_VERSION; return version; } void child_error(s,image) char *s,*image; { /* JGOFS_ERR_PREFIX is &x (defined in core.h) */ printf("%s startchild %s error in child process\n%s: %s\n", JGOFS_ERR_PREFIX,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(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