local = TRUE;
local = true;
CompatRunCommand(cmdp, gnp)    void *	  cmdp; 	/* Command to execute */    void *	  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 */		  doExecute;	/* Execute the command */    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);    doExecute = !noExecute;    cmdNode = Lst_Member(&gn->commands, cmd);    cmdStart = Var_Subst(cmd, &gn->context, 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 1;    } else	cmd = cmdStart;    Lst_Replace(cmdNode, cmdStart);    if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {	Lst_AtEnd(&ENDNode->commands, cmdStart);	return 1;    } else if (strcmp(cmdStart, "...") == 0) {	gn->type |= OP_SAVE_CMDS;	return 1;    }    for (;; cmd++) {	if (*cmd == '@')	    silent = DEBUG(LOUD) ? FALSE : TRUE;	else if (*cmd == '-')	    errCheck = FALSE;	else if (*cmd == '+')	    doExecute = TRUE;	else	    break;    }    while (isspace(*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 (!doExecute)	return 1;    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] = 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, &bp);	switch (shellneed(av)) {	case -1: /* handled internally */		free(bp);		free(av);		return 1;	case 1:		shargv[1] = errCheck ? "-ec" : "-c";		shargv[2] = cmd;		shargv[3] = NULL;		free(av);		free(bp);		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 == -1)	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, 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;}