Lst_AtEnd(ENDNode->commands, (ClientData)cmdStart);
Lst_AtEnd(ENDNode->commands, cmdStart);
CompatRunCommand (cmdp, gnp)    ClientData    cmdp;	    	/* Command to execute */    ClientData    gnp;    	/* Node from which the command came */{    char    	  *cmdStart;	/* Start of expanded command */    char *cp, *bp = NULL;    Boolean 	  silent,   	/* Don't print command */		  errCheck; 	/* Check errors */    int 	  reason;   	/* Reason for child's death */    int	    	  status;   	/* Description of child's death */    int	    	  cpid;	    	/* Child actually found */    ReturnStatus  stat;	    	/* Status of fork */    LstNode 	  cmdNode;  	/* Node where current command is located */    char    	  **av;	    	/* Argument vector for thing to exec */    int	    	  argc;	    	/* Number of arguments in av or 0 if not				 * dynamically allocated */    Boolean 	  local;    	/* TRUE if command should be executed				 * locally */    char	  *cmd = (char *) cmdp;    GNode	  *gn = (GNode *) gnp;    static char	*shargv[4] = { "/bin/sh" };    /*     * Avoid clobbered variable warnings by forcing the compiler     * to ``unregister'' variables     */#if __GNUC__    (void) &av;    (void) &errCheck;#endif    silent = gn->type & OP_SILENT;    errCheck = !(gn->type & OP_IGNORE);    cmdNode = Lst_Member (gn->commands, (ClientData)cmd);    cmdStart = Var_Subst(cmd, gn, FALSE);    /*     * brk_string will return an argv with a NULL in av[0], thus causing     * execvp to choke and die horribly. Besides, how can we execute a null     * command? In any case, we warn the user that the command expanded to     * nothing (is this the right thing to do?).     */    if (*cmdStart == '\0') {	free(cmdStart);	Error("%s expands to empty string", cmd);	return(0);    } else {	cmd = cmdStart;    }    Lst_Replace (cmdNode, (ClientData)cmdStart);    if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {	Lst_AtEnd(ENDNode->commands, (ClientData)cmdStart);	return(0);    } else if (strcmp(cmdStart, "...") == 0) {	gn->type |= OP_SAVE_CMDS;	return(0);    }    while ((*cmd == '@') || (*cmd == '-')) {	if (*cmd == '@') {	    silent = TRUE;	} else {	    errCheck = FALSE;	}	cmd++;    }    while (isspace((unsigned char)*cmd))	cmd++;    /*     * Search for meta characters in the command. If there are no meta     * characters, there's no need to execute a shell to execute the     * command.     */    for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {	continue;    }    /*     * Print the command before echoing if we're not supposed to be quiet for     * this one. We also print the command if -n given.     */    if (!silent || noExecute) {	printf ("%s\n", cmd);	fflush(stdout);    }    /*     * If we're not supposed to execute any commands, this is as far as     * we go...     */    if (noExecute) {	return (0);    }    if (*cp != '\0') {	/*	 * If *cp isn't the null character, we hit a "meta" character and	 * need to pass the command off to the shell. We give the shell the	 * -e flag as well as -c if it's supposed to exit when it hits an	 * error.	 */	shargv[1] = (errCheck ? "-ec" : "-c");	shargv[2] = cmd;	shargv[3] = (char *)NULL;	av = shargv;	argc = 0;    } else {	/*	 * No meta-characters, so probably no need to exec a shell. 	 * Break the command into words to form an argument vector 	 * we can execute.	 */	av = brk_string(cmd, &argc, TRUE, &bp);	switch(shellneed(av)) {	case -1: /* handled internally */		free(bp);		free(av);		return 0;	case 1:		shargv[1] = (errCheck ? "-ec" : "-c");		shargv[2] = cmd;		shargv[3] = (char *)NULL;		free(bp);		free(av);		bp = NULL;		av = shargv;		argc = 0;		break;	default: /* nothing needed */		break;	}    }    local = TRUE;    /*     * Fork and execute the single command. If the fork fails, we abort.     */    cpid = vfork();    if (cpid < 0) {	Fatal("Could not fork");    }    if (cpid == 0) {	if (local) {	    execvp(av[0], av);	    if (errno == ENOENT)	    	fprintf(stderr, "%s: not found\n", av[0]);	    else		perror(av[0]);	} else {	    (void)execv(av[0], av);	}	_exit(1);    }    if (bp) {    	free(av);	free(bp);    }    free(cmdStart);    Lst_Replace(cmdNode, (ClientData)NULL);    /*     * The child is off and running. Now all we can do is wait...     */    while (1) {	while ((stat = wait(&reason)) != cpid) {	    if (stat == -1 && errno != EINTR) {		break;	    }	}	if (stat > -1) {	    if (WIFSTOPPED(reason)) {		status = WSTOPSIG(reason);		/* stopped */	    } else if (WIFEXITED(reason)) {		status = WEXITSTATUS(reason);		/* exited */		if (status != 0) {		    printf ("*** Error code %d", status);		}	    } else {		status = WTERMSIG(reason);		/* signaled */		printf ("*** Signal %d", status);	    }	    if (!WIFEXITED(reason) || (status != 0)) {		if (errCheck) {		    gn->made = ERROR;		    if (keepgoing) {			/*			 * Abort the current target, but let others			 * continue.			 */			printf (" (continuing)\n");		    }		} else {		    /*		     * Continue executing commands for this target.		     * If we return 0, this will happen...		     */		    printf (" (ignored)\n");		    status = 0;		}	    }	    break;	} else {	    Fatal ("error in wait: %d", stat);	    /*NOTREACHED*/	}    }    return (status);}