/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.1 (the "License"). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include <libc.h> /* first to get rid of pre-comp warning */ #include <mach/mach.h> /* first to get rid of pre-comp warning */ #include "stdio.h" #include <signal.h> #include <sys/wait.h> #include "stuff/errors.h" #include "stuff/allocate.h" #include "stuff/execute.h" /* * execute() does an execvp using the argv passed to it. If the parameter * verbose is non-zero the command is printed to stderr. A non-zero return * value indicates success zero indicates failure. */ __private_extern__ int execute( char **argv, long verbose) { char *name, **p; int forkpid, waitpid, termsig; #ifndef __OPENSTEP__ int waitstatus; #else union wait waitstatus; #endif name = argv[0]; if(verbose){ fprintf(stderr, "+ %s ", name); p = &(argv[1]); while(*p != (char *)0) fprintf(stderr, "%s ", *p++); fprintf(stderr, "\n"); } forkpid = fork(); if(forkpid == -1) system_fatal("can't fork a new process to execute: %s", name); if(forkpid == 0){ if(execvp(name, argv) == -1) system_fatal("can't find or exec: %s", name); return(1); /* can't get here, removes a warning from the compiler */ } else{ waitpid = wait(&waitstatus); if(waitpid == -1) system_fatal("wait on forked process %d failed", forkpid); #ifndef __OPENSTEP__ termsig = WTERMSIG(waitstatus); #else termsig = waitstatus.w_termsig; #endif if(termsig != 0 && termsig != SIGINT) fatal("fatal error in %s", name); return( #ifndef __OPENSTEP__ WEXITSTATUS(waitstatus) == 0 && #else waitstatus.w_retcode == 0 && #endif termsig == 0); } } /* * runlist is used by the routine execute_list() to execute a program and it * contains the command line arguments. Strings are added to it by * add_execute_list(). The routine reset_execute_list() resets it for new use. */ static struct { int size; int next; char **strings; } runlist; /* * This routine is passed a string to be added to the list of strings for * command line arguments. */ __private_extern__ void add_execute_list( char *str) { if(runlist.strings == (char **)0){ runlist.next = 0; runlist.size = 128; runlist.strings = allocate(runlist.size * sizeof(char **)); } if(runlist.next + 1 >= runlist.size){ runlist.strings = reallocate(runlist.strings, (runlist.size * 2) * sizeof(char **)); runlist.size *= 2; } runlist.strings[runlist.next++] = str; runlist.strings[runlist.next] = (char *)0; } /* * This routine reset the list of strings of command line arguments so that * an new command line argument list can be built. */ __private_extern__ void reset_execute_list(void) { runlist.next = 0; } /* * This routine calls execute() to run the command built up in the runlist * strings. */ __private_extern__ int execute_list( long verbose) { return(execute(runlist.strings, verbose)); }