From d352702b5593e813b60aba16edb7ff746d0a7e78 Mon Sep 17 00:00:00 2001 From: ketmar Date: Thu, 18 Aug 2011 13:42:28 +0300 Subject: [PATCH] cleanup of exec --- 0build_common.sh | 6 +- src/Jamfile | 21 +- src/{execunix.c => execcmd.c} | 173 ++++++---------- src/execcmd.h | 21 +- src/execnt.c | 459 ------------------------------------------ src/jam.c | 3 +- src/jam.h | 3 - 7 files changed, 84 insertions(+), 602 deletions(-) rename src/{execunix.c => execcmd.c} (68%) delete mode 100644 src/execnt.c diff --git a/0build_common.sh b/0build_common.sh index 3f81df6..b9152ae 100644 --- a/0build_common.sh +++ b/0build_common.sh @@ -44,7 +44,7 @@ rm ${DESTPATH}/* 2>/dev/null docc "builtins" docc "command" docc "compile" -docc "execunix" +docc "execcmd" docc "file${XOS}" docc "pathunix" @@ -75,11 +75,11 @@ docc "hdrmacro" docc "kstrings" echo "Ar libjam.a" -${AR} ${BUILDPATH}/obj/libjam.a ${BUILDPATH}/obj/builtins.o ${BUILDPATH}/obj/command.o ${BUILDPATH}/obj/compile.o ${BUILDPATH}/obj/execunix.o ${BUILDPATH}/obj/file${XOS}.o ${BUILDPATH}/obj/pathunix.o ${BUILDPATH}/obj/jamgram.o ${BUILDPATH}/obj/expand.o ${BUILDPATH}/obj/glob.o ${BUILDPATH}/obj/hash.o ${BUILDPATH}/obj/headers.o ${BUILDPATH}/obj/lists.o ${BUILDPATH}/obj/make.o ${BUILDPATH}/obj/make1.o ${BUILDPATH}/obj/newstr.o ${BUILDPATH}/obj/option.o ${BUILDPATH}/obj/parse.o ${BUILDPATH}/obj/regexp.o ${BUILDPATH}/obj/rules.o ${BUILDPATH}/obj/scan.o ${BUILDPATH}/obj/search.o ${BUILDPATH}/obj/timestamp.o ${BUILDPATH}/obj/variable.o ${BUILDPATH}/obj/hdrmacro.o ${BUILDPATH}/obj/kstrings.o +${AR} ${BUILDPATH}/obj/libjam.a ${BUILDPATH}/obj/builtins.o ${BUILDPATH}/obj/command.o ${BUILDPATH}/obj/compile.o ${BUILDPATH}/obj/execcmd.o ${BUILDPATH}/obj/file${XOS}.o ${BUILDPATH}/obj/pathunix.o ${BUILDPATH}/obj/jamgram.o ${BUILDPATH}/obj/expand.o ${BUILDPATH}/obj/glob.o ${BUILDPATH}/obj/hash.o ${BUILDPATH}/obj/headers.o ${BUILDPATH}/obj/lists.o ${BUILDPATH}/obj/make.o ${BUILDPATH}/obj/make1.o ${BUILDPATH}/obj/newstr.o ${BUILDPATH}/obj/option.o ${BUILDPATH}/obj/parse.o ${BUILDPATH}/obj/regexp.o ${BUILDPATH}/obj/rules.o ${BUILDPATH}/obj/scan.o ${BUILDPATH}/obj/search.o ${BUILDPATH}/obj/timestamp.o ${BUILDPATH}/obj/variable.o ${BUILDPATH}/obj/hdrmacro.o ${BUILDPATH}/obj/kstrings.o echo "Ranlib libjam.a" ${RANLIB} ${BUILDPATH}/obj/libjam.a -rm -f ${BUILDPATH}/obj/builtins.o ${BUILDPATH}/obj/command.o ${BUILDPATH}/obj/compile.o ${BUILDPATH}/obj/execunix.o ${BUILDPATH}/obj/file${XOS}.o ${BUILDPATH}/obj/pathunix.o ${BUILDPATH}/obj/jamgram.o ${BUILDPATH}/obj/expand.o ${BUILDPATH}/obj/glob.o ${BUILDPATH}/obj/hash.o ${BUILDPATH}/obj/headers.o ${BUILDPATH}/obj/lists.o ${BUILDPATH}/obj/make.o ${BUILDPATH}/obj/make1.o ${BUILDPATH}/obj/newstr.o ${BUILDPATH}/obj/option.o ${BUILDPATH}/obj/parse.o ${BUILDPATH}/obj/regexp.o ${BUILDPATH}/obj/rules.o ${BUILDPATH}/obj/scan.o ${BUILDPATH}/obj/search.o ${BUILDPATH}/obj/timestamp.o ${BUILDPATH}/obj/variable.o ${BUILDPATH}/obj/hdrmacro.o ${BUILDPATH}/obj/kstrings.o +rm -f ${BUILDPATH}/obj/builtins.o ${BUILDPATH}/obj/command.o ${BUILDPATH}/obj/compile.o ${BUILDPATH}/obj/execcmd.o ${BUILDPATH}/obj/file${XOS}.o ${BUILDPATH}/obj/pathunix.o ${BUILDPATH}/obj/jamgram.o ${BUILDPATH}/obj/expand.o ${BUILDPATH}/obj/glob.o ${BUILDPATH}/obj/hash.o ${BUILDPATH}/obj/headers.o ${BUILDPATH}/obj/lists.o ${BUILDPATH}/obj/make.o ${BUILDPATH}/obj/make1.o ${BUILDPATH}/obj/newstr.o ${BUILDPATH}/obj/option.o ${BUILDPATH}/obj/parse.o ${BUILDPATH}/obj/regexp.o ${BUILDPATH}/obj/rules.o ${BUILDPATH}/obj/scan.o ${BUILDPATH}/obj/search.o ${BUILDPATH}/obj/timestamp.o ${BUILDPATH}/obj/variable.o ${BUILDPATH}/obj/hdrmacro.o ${BUILDPATH}/obj/kstrings.o docc "mkjambase" dolink "mkjambase" diff --git a/src/Jamfile b/src/Jamfile index 38e417c..9e3d734 100644 --- a/src/Jamfile +++ b/src/Jamfile @@ -1,23 +1,10 @@ SubDir TOP src ; -if $(NT) || $(WINE_MINGW) { - code = - execunix.c - filent.c - pathunix.c - ; -} else { - code = - execunix.c - fileunix.c - pathunix.c - ; -} +if $(NT) || $(WINE_MINGW) { code += filent.c ; } else { code += fileunix.c ; } # Do we know yacc? -if $(YACC) { code += jamgram.y ; } -else { code += jamgram.c ; } +if $(YACC) { code += jamgram.y ; } else { code += jamgram.c ; } if $(YACC) && $(SUFEXE) = "" { @@ -45,8 +32,8 @@ if $(JAM_TOOLSET) = MINGW { Library libjam.a : - builtins.c command.c compile.c $(code) expand.c - glob.c hash.c headers.c lists.c make.c make1.c + builtins.c command.c compile.c execcmd.c expand.c $(code) + glob.c hash.c headers.c lists.c make.c make1.c pathunix.c newstr.c option.c parse.c regexp.c rules.c scan.c search.c timestamp.c variable.c hdrmacro.c kstrings.c diff --git a/src/execunix.c b/src/execcmd.c similarity index 68% rename from src/execunix.c rename to src/execcmd.c index d9b634a..27d26a1 100644 --- a/src/execunix.c +++ b/src/execcmd.c @@ -3,9 +3,8 @@ * * This file is part of Jam - see jam.c for Copyright information. */ - /* - * execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS + * execcmd.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS * * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp(). * The default is: @@ -37,29 +36,29 @@ * 11/04/02 (seiwald) - const-ing for string literals * 12/27/02 (seiwald) - grist .bat file with pid for system uniqueness */ -# include "jam.h" -# include "lists.h" -# include "execcmd.h" -# include +#include + +#include "jam.h" +#include "lists.h" +#include "execcmd.h" -# ifdef USE_EXECUNIX -# ifdef OS_OS2 +#ifdef OS_OS2 # define USE_EXECNT # include -# endif +#endif -# ifdef OS_NT +#ifdef OS_NT # define USE_EXECNT # include # define WIN32_LEAN_AND_MEAN -# include /* do the ugly deed */ +# include /* do the ugly deed */ # define USE_MYWAIT -# if !defined( __BORLANDC__ ) -# define wait my_wait +# if !defined(__BORLANDC__) +# define wait my_wait static int my_wait (int *status); # endif -# endif +#endif //extern int execvp (const char *file, const char *argv[]); @@ -82,7 +81,7 @@ static struct { * onintr() - bump intr to note command interruption */ void onintr (int disp) { - intr++; + ++intr; printf("...interrupted\n"); } @@ -90,71 +89,57 @@ void onintr (int disp) { /* * execcmd() - launch an async command execution */ -void execcmd ( - char *string, - void (*func) (void *closure, int status), - void *closure, - LIST *shell) -{ +void execcmd (const char *string, void (*func) (void *closure, int status), void *closure, LIST *shell) { int pid; int slot; const char *argv[MAXARGC+1]; /* +1 for NULL */ #ifdef USE_EXECNT char *p; #endif - - /* Find a slot in the running commands table for this one. */ - for (slot = 0; slot < MAXJOBS; slot++) if (!cmdtab[slot].pid) break; - if (slot == MAXJOBS) { - printf("no slots for child!\n"); - exit(EXITBAD); - } - + // + /* find a slot in the running commands table for this one */ + for (slot = 0; slot < MAXJOBS; ++slot) if (!cmdtab[slot].pid) break; + if (slot == MAXJOBS) { printf("no slots for child!\n"); exit(EXITBAD); } #ifdef USE_EXECNT if (!cmdtab[slot].tempfile) { char *tempdir; - + // if (!(tempdir = getenv("TEMP")) && !(tempdir = getenv("TMP"))) tempdir = "\\temp"; /* +32 is room for \jamXXXXXtSS.bat (at least) */ cmdtab[slot].tempfile = malloc(strlen(tempdir)+32); sprintf(cmdtab[slot].tempfile, "%s\\jam%ut%d.bat", tempdir, (unsigned int)(GetCurrentProcessId()), slot); } - - /* Trim leading, ending white space */ - while(isspace(*string)) ++string; + /* trim leading, ending white space */ + while (isspace(*string)) ++string; p = strchr(string, '\n'); while (p && isspace(*p)) ++p; - - /* If multi line, or too long, or JAMSHELL is set, write to bat file. */ - /* Otherwise, exec directly. */ - /* Frankly, if it is a single long line I don't think the */ - /* command interpreter will do any better -- it will fail. */ + /* If multi line, or too long, or JAMSHELL is set, write to bat file, otherwise, exec directly */ + /* frankly, if it is a single long line I don't think the */ + /* command interpreter will do any better -- it will fail */ if ((p && *p) || strlen(string) > MAXLINE || shell) { FILE *f; - - /* Write command to bat file. */ + // + /* write command to bat file */ f = fopen(cmdtab[slot].tempfile, "w"); fputs(string, f); fclose(f); string = cmdtab[slot].tempfile; } #endif - - /* Forumulate argv */ - /* If shell was defined, be prepared for % and ! subs. */ - /* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */ + /* forumulate argv */ + /* if shell was defined, be prepared for % and ! subs, */ + /* otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT) */ if (shell) { int i; char jobno[4]; int gotpercent = 0; - + // sprintf(jobno, "%d", slot+1); - - for (i = 0; shell && i < MAXARGC; i++, shell = list_next(shell)) { + for (i = 0; shell && i < MAXARGC; ++i, shell = list_next(shell)) { switch (shell->string[0]) { - case '%': argv[i] = string; gotpercent++; break; + case '%': argv[i] = string; ++gotpercent; break; case '!': argv[i] = jobno; break; - default: argv[i] = shell->string; + default: argv[i] = shell->string; break; } if (DEBUG_EXECCMD) printf("argv[%d] = '%s'\n", i, argv[i]); } @@ -171,40 +156,25 @@ void execcmd ( argv[2] = string; argv[3] = 0; } - - /* Catch interrupts whenever commands are running. */ + /* catch interrupts whenever commands are running */ if (!cmdsrunning++) istat = signal(SIGINT, onintr); - - /* Start the command */ + /* start the command */ #ifdef USE_EXECNT - if ((pid = spawnvp(P_NOWAIT, argv[0], argv)) == -1) { - perror("spawn"); - exit(EXITBAD); - } + if ((pid = spawnvp(P_NOWAIT, argv[0], argv)) == -1) { perror("spawn"); exit(EXITBAD); } #else -#ifdef NO_VFORK - if ((pid = fork()) == 0) { - execvp(argv[0], argv); - _exit(127); - } -#else - if ((pid = vfork()) == 0) { - execvp(argv[0], (void *)argv); - _exit(127); - } -#endif - if (pid == -1) { - perror("vfork"); - exit(EXITBAD); - } +# ifdef NO_VFORK + if ((pid = fork()) == 0) { execvp(argv[0], argv); _exit(127); } +# else + if ((pid = vfork()) == 0) { execvp(argv[0], (void *)argv); _exit(127); } +# endif + if (pid == -1) { perror("vfork"); exit(EXITBAD); } #endif - /* Save the operation for execwait() to find. */ + /* save the operation for execwait() to find */ cmdtab[slot].pid = pid; cmdtab[slot].func = func; cmdtab[slot].closure = closure; - - /* Wait until we're under the limit of concurrent commands. */ - /* Don't trust globs.jobs alone. */ + /* wait until we're under the limit of concurrent commands */ + /* don't trust globs.jobs alone */ while (cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs) if (!execwait()) break; } @@ -212,42 +182,34 @@ void execcmd ( /* * execwait() - wait and drive at most one execution completion */ -int execwait () { +int execwait (void) { int i; int status, w; int rstat; - - /* Handle naive make1() which doesn't know if cmds are running. */ + // + /* handle naive make1() which doesn't know if cmds are running */ if (!cmdsrunning) return 0; - /* Pick up process pid and status */ + /* pick up process pid and status */ while ((w = wait(&status)) == -1 && errno == EINTR) ; if (w == -1) { printf("child process(es) lost!\n"); perror("wait"); exit(EXITBAD); } - - /* Find the process in the cmdtab. */ - for (i = 0; i < MAXJOBS; i++) if (w == cmdtab[i].pid) break; - if (i == MAXJOBS) { - printf("waif child found!\n"); - exit(EXITBAD); - } + /* find the process in the cmdtab */ + for (i = 0; i < MAXJOBS; ++i) if (w == cmdtab[i].pid) break; + if (i == MAXJOBS) { printf("waif child found!\n"); exit(EXITBAD); } #ifdef USE_EXECNT - /* Clear the temp file */ + /* clear the temp file */ unlink(cmdtab[i].tempfile); #endif - - /* Drive the completion */ + /* drive the completion */ if (!--cmdsrunning) signal(SIGINT, istat); - if (intr) rstat = EXEC_CMD_INTR; else if (w == -1 || status != 0) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; - cmdtab[i].pid = 0; (*cmdtab[i].func)(cmdtab[i].closure, rstat); - return 1; } @@ -257,43 +219,38 @@ static int my_wait (int *status) { int i, num_active = 0; DWORD exitcode, waitcode; static HANDLE *active_handles = 0; - + // if (!active_handles) active_handles = (HANDLE *)malloc(globs.jobs*sizeof(HANDLE)); /* first see if any non-waited-for processes are dead, and return if so. */ - for (i = 0; i < globs.jobs; i++) { + for (i = 0; i < globs.jobs; ++i) { if (cmdtab[i].pid) { if (GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode)) { if (exitcode == STILL_ACTIVE) { active_handles[num_active++] = (HANDLE)cmdtab[i].pid; } else { CloseHandle((HANDLE)cmdtab[i].pid); - *status = (int)((exitcode & 0xff) << 8); + *status = (int)((exitcode&0xff)<<8); return cmdtab[i].pid; } - } else goto FAILED; + } else { + goto failed; + } } } /* if a child exists, wait for it to die */ - if (!num_active) { - errno = ECHILD; - return -1; - } + if (!num_active) { errno = ECHILD; return -1; } waitcode = WaitForMultipleObjects(num_active, active_handles, FALSE, INFINITE); if (waitcode != WAIT_FAILED) { if (waitcode >= WAIT_ABANDONED_0 && waitcode < WAIT_ABANDONED_0+num_active) i = waitcode-WAIT_ABANDONED_0; else i = waitcode-WAIT_OBJECT_0; if (GetExitCodeProcess(active_handles[i], &exitcode)) { CloseHandle(active_handles[i]); - *status = (int)((exitcode & 0xff) << 8); + *status = (int)((exitcode&0xff)<<8); return (int)active_handles[i]; } } - -FAILED: +failed: errno = GetLastError(); return -1; } -# endif /* USE_MYWAIT */ - - -# endif /* USE_EXECUNIX */ +#endif /* USE_MYWAIT */ diff --git a/src/execcmd.h b/src/execcmd.h index 06103e5..9ce8fec 100644 --- a/src/execcmd.h +++ b/src/execcmd.h @@ -3,21 +3,22 @@ * * This file is part of Jam - see jam.c for Copyright information. */ - /* * execcmd.h - execute a shell script * * 05/04/94 (seiwald) - async multiprocess interface */ +#ifndef JAMH_EXECCMD_H +#define JAMH_EXECCMD_H + + +extern void execcmd (const char *string, void (*func)(void *closure, int status), void *closure, LIST *shell ); +extern int execwait (void); + -void execcmd (char *string, - void (*func)(void *closure, int status), - void *closure, - LIST *shell -); +#define EXEC_CMD_OK (0) +#define EXEC_CMD_FAIL (1) +#define EXEC_CMD_INTR (2) -int execwait (void); -# define EXEC_CMD_OK 0 -# define EXEC_CMD_FAIL 1 -# define EXEC_CMD_INTR 2 +#endif diff --git a/src/execnt.c b/src/execnt.c deleted file mode 100644 index 0b2fc59..0000000 --- a/src/execnt.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright 1993, 1995 Christopher Seiwald. - * - * This file is part of Jam - see jam.c for Copyright information. - */ - -# include "jam.h" -# include "lists.h" -# include "execcmd.h" -# include - -# ifdef USE_EXECNT - -# define WIN32_LEAN_AND_MEAN -# include /* do the ugly deed */ -# include - -# if !defined( __BORLANDC__ ) && !defined( OS_OS2 ) -# define wait my_wait -static int my_wait (int *status); -# endif - - -/* - * execnt.c - execute a shell command on Windows NT and Windows 95/98 - * - * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp(). - * The default is: - * - * /bin/sh -c % [ on UNIX/AmigaOS ] - * cmd.exe /c % [ on Windows NT ] - * - * Each word must be an individual element in a jam variable value. - * - * In $(JAMSHELL), % expands to the command string and ! expands to - * the slot number (starting at 1) for multiprocess (-j) invocations. - * If $(JAMSHELL) doesn't include a %, it is tacked on as the last - * argument. - * - * Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work! - * - * External routines: - * execcmd() - launch an async command execution - * execwait() - wait and drive at most one execution completion - * - * Internal routines: - * onintr() - bump intr to note command interruption - * - * 04/08/94 (seiwald) - Coherent/386 support added. - * 05/04/94 (seiwald) - async multiprocess interface - * 01/22/95 (seiwald) - $(JAMSHELL) support - * 06/02/97 (gsar) - full async multiprocess support for Win32 - */ - -static int intr = 0; -static int cmdsrunning = 0; -static void (*istat) (int); - -static int is_nt_351 = 0; -static int is_win95 = 1; -static int is_win95_defined = 0; - - -static struct { - int pid; /* on win32, a real process handle */ - void (*func) (void *closure, int status); - void *closure; - char *tempfile; -} cmdtab[MAXJOBS] = {{0}}; - - -static void set_is_win95 (void) { - OSVERSIONINFO os_info; - - os_info.dwOSVersionInfoSize = sizeof(os_info); - os_info.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; - GetVersionEx(&os_info); - - is_win95 = (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); - is_win95_defined = 1; - - /* now, test wether we're running Windows 3.51 */ - /* this is later used to limit the system call command length */ - if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) is_nt_351 = (os_info.dwMajorVersion == 3); -} - - -static char **string_to_args (const char *string, int *pcount) { - int total = strlen(string); - int in_quote = 0, num_args; - char *line; - char *p; - char **arg; - char **args; - - *pcount = 0; - /* do not copy trailing newlines, if any */ - { - int i; - for (i = total-1; i > 0; i--) { - if (string[i] != '\n' && string[i] != '\r') break; - total--; - } - } - - /* first of all, copy the input string */ - line = (char *)malloc(total+2); - if (!line) return 0; - memcpy(line+1, string, total); - line[0] = 0; - line[total+1] = 0; - - in_quote = 0; - for (p = line+1; p[0]; p++) { - switch (p[0]) { - case '"': in_quote = !in_quote; break; - case ' ': case '\t': if (!in_quote) p[0] = 0; - default: ; - } - } - - /* now count the arguments.. */ - for (p = line; p < line+total+1; p++) if (!p[0] && p[1]) num_args++; - - /* allocate the args array */ - args = (char **)malloc(num_args*sizeof(char*)+2); - if (!args) { free(line); return 0; } - - arg = args+1; - for (p = line; p < line+total+1; p++) if (!p[0] && p[1]) { arg[0] = p+1; arg++; } - arg[0] = 0; - *pcount = num_args; - args[0] = line; - return args+1; -} - - -static void free_args (char **args) { - free(args[-1]); - free(args-1); -} - - -/* process a "del" or "erase" command under Windows 95/98 */ -static int process_del (char *command) { - char **arg; - char *p = command, *q; - int wildcard = 0, result = 0; - - /* first of all, skip the command itself */ - if (p[0] == 'd') p += 3; /* assumes "del..;" */ - else if (p[0] == 'e') p += 5; /* assumes "erase.." */ - else return 1; /* invalid command */ - - /* process all targets independently */ - for (;;) { - /* skip leading spaces */ - while (*p && isspace(*p)) p++; - /* exit if we encounter an end of string */ - if (!*p) return 0; - /* ignore toggles/flags */ - if (*p == '/') { - p++; - while (*p && isalnum(*p)) p++; - } else { - int in_quote = 0; - int wildcard = 0; - int go_on = 1; - - q = p; - while (go_on) { - switch (*p) { - case '"': in_quote = !in_quote; break; - case '?': case '*': if (!in_quote) wildcard = 1; break; - case '\0': if (in_quote) return 1; /* fall-through */ - case ' ': case '\t': - if (!in_quote) { - int len = p-q; - int result; - char *line; - - /* q..p-1 contains the delete argument */ - if (len <= 0) return 1; - line = (char *)malloc((len+4+1)*sizeof(char)); - if (!line) return 1; - - strncpy(line, "del ", 4); - strncpy(line+4, q, len); - line[len+4] = '\0'; - - if (wildcard) result = system(line); else result = !DeleteFile(line+4); - - free(line); - if (result) return 1; - go_on = 0; - } - break; - default: ; - } - p++; - } /* while (go_on) */ - } - } -} - - -/* - * onintr() - bump intr to note command interruption - */ -void onintr (int disp) { - intr++; - printf("...interrupted\n"); -} - - -/* - * execcmd() - launch an async command execution - */ -void execcmd ( - char *string, - void (*func) (void *closure, int status), - void *closure, - LIST *shell) -{ - int pid; - int slot; - int max_line; - char *argv[ MAXARGC+1]; /* +1 for NULL */ - char *p; - - if (!is_win95_defined) set_is_win95(); - /* Find a slot in the running commands table for this one. */ - if (is_win95) { - /* only synchronous spans are supported on Windows 95/98 */ - slot = 0; - } else { - for (slot = 0; slot < MAXJOBS; slot++) if (!cmdtab[slot].pid) break; - } - if (slot == MAXJOBS) { - printf("no slots for child!\n"); - exit(EXITBAD); - } - - if (!cmdtab[slot].tempfile) { - char *tempdir; - - if (!(tempdir = getenv("TEMP")) && !(tempdir = getenv("TMP"))) tempdir = "\\temp"; - cmdtab[slot].tempfile = malloc(strlen(tempdir)+14); - - sprintf(cmdtab[slot].tempfile, "%s\\jamtmp%02d.bat", tempdir, slot); - } - - /* Trim leading, ending white space */ - while (isspace(*string)) ++string; - p = strchr(string, '\n'); - while (p && isspace(*p)) ++p; - - /* on Windows NT 3.51, the maximul line length is 996 bytes !! */ - /* while it's much bigger NT 4 and 2k */ - max_line = is_nt_351 ? 996 : MAXLINE; - - /* If multi line, or too long, or JAMSHELL is set, write to bat file. */ - /* Otherwise, exec directly. */ - /* Frankly, if it is a single long line I don't think the */ - /* command interpreter will do any better -- it will fail. */ - if (p && *p || strlen(string) > max_line || shell) { - FILE *f; - - /* Write command to bat file. */ - f = fopen(cmdtab[slot].tempfile, "w"); - fputs(string, f); - fclose(f); - string = cmdtab[slot].tempfile; - } - - /* Forumulate argv */ - /* If shell was defined, be prepared for % and ! subs. */ - /* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */ - if (shell) { - int i; - char jobno[4]; - int gotpercent = 0; - - sprintf(jobno, "%d", slot+1); - for (i = 0; shell && i < MAXARGC; i++, shell = list_next(shell)) { - switch (shell->string[0]) { - case '%': argv[i] = string; gotpercent++; break; - case '!': argv[i] = jobno; break; - default: argv[i] = shell->string; - } - if (DEBUG_EXECCMD) printf("argv[%d] = '%s'\n", i, argv[i]); - } - if (!gotpercent) argv[i++] = string; - argv[i] = 0; - } else { - /* don't worry, this is ignored on Win95/98, see later.. */ - argv[0] = "cmd.exe"; - argv[1] = "/Q/C"; /* anything more is non-portable */ - argv[2] = string; - argv[3] = 0; - } - - /* Catch interrupts whenever commands are running. */ - if (!cmdsrunning++) istat = signal(SIGINT, onintr); - - /* Start the command */ - /* on Win95, we only do a synchronous call */ - if (is_win95) { - static const char* hard_coded[] = { - "del", "erase", "copy", "mkdir", "rmdir", "cls", "dir", - "ren", "rename", "move", 0 - }; - - const char **keyword; - int len, spawn = 1; - int result; - - for (keyword = hard_coded; keyword[0]; keyword++) { - len = strlen(keyword[0]); - if ( strnicmp(string, keyword[0], len) == 0 && !isalnum(string[len])) { - /* this is one of the hard coded symbols, use 'system' to run */ - /* them.. except for "del"/"erase" */ - if (keyword-hard_coded < 2) result = process_del(string); - else result = system(string); - spawn = 0; - break; - } - } - - if (spawn) { - char **args; - int num_args; - - /* convert the string into an array of arguments */ - /* we need to take care of double quotes !! */ - args = string_to_args(string, &num_args); - if (args) { -#if 0 - char **arg; - fprintf(stderr, "%s: ", args[0]); - arg = args+1; - while (arg[0]) { - fprintf(stderr, " {%s}", arg[0]); - arg++; - } - fprintf(stderr, "\n"); -#endif - result = spawnvp(P_WAIT, args[0], args); - free_args(args); - } else result = 1; - } - func(closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK); - return; - } - - /* the rest is for Windows NT only */ - if ((pid = spawnvp(P_NOWAIT, argv[0], argv)) == -1) { - perror("spawn"); - exit(EXITBAD); - } - /* Save the operation for execwait() to find. */ - cmdtab[slot].pid = pid; - cmdtab[slot].func = func; - cmdtab[slot].closure = closure; - - /* Wait until we're under the limit of concurrent commands. */ - /* Don't trust globs.jobs alone. */ - while (cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs) if (!execwait()) break; -} - - -/* - * execwait() - wait and drive at most one execution completion - */ -int execwait () { - int i; - int status, w; - int rstat; - - /* Handle naive make1() which doesn't know if cmds are running. */ - if (!cmdsrunning) return 0; - if (is_win95) return 0; - - /* Pick up process pid and status */ - while ((w = wait(&status)) == -1 && errno == EINTR) ; - - if (w == -1) { - printf("child process(es) lost!\n"); - perror("wait"); - exit(EXITBAD); - } - - /* Find the process in the cmdtab. */ - for (i = 0; i < MAXJOBS; i++) if (w == cmdtab[i].pid) break; - if (i == MAXJOBS) { - printf("waif child found!\n"); - exit(EXITBAD); - } - /* Drive the completion */ - if (!--cmdsrunning) signal(SIGINT, istat); - - if (intr) rstat = EXEC_CMD_INTR; - else if (w == -1 || status != 0) rstat = EXEC_CMD_FAIL; - else rstat = EXEC_CMD_OK; - - cmdtab[i].pid = 0; - - (*cmdtab[i].func)(cmdtab[i].closure, rstat); - - return 1; -} - - -# if !defined( __BORLANDC__ ) -static int my_wait (int *status) { - int i, num_active = 0; - DWORD exitcode, waitcode; - static HANDLE *active_handles = 0; - - if (!active_handles) active_handles = (HANDLE *)malloc(globs.jobs*sizeof(HANDLE)); - /* first see if any non-waited-for processes are dead, and return if so. */ - for (i = 0; i < globs.jobs; i++) { - if (cmdtab[i].pid) { - if (GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode)) { - if (exitcode == STILL_ACTIVE) { - active_handles[num_active++] = (HANDLE)cmdtab[i].pid; - } else { - CloseHandle((HANDLE)cmdtab[i].pid); - *status = (int)((exitcode & 0xff) << 8); - return cmdtab[i].pid; - } - } else goto FAILED; - } - } - /* if a child exists, wait for it to die */ - if (!num_active) { - errno = ECHILD; - return -1; - } - waitcode = WaitForMultipleObjects(num_active, active_handles, FALSE, INFINITE); - if (waitcode != WAIT_FAILED) { - if (waitcode >= WAIT_ABANDONED_0 && waitcode < WAIT_ABANDONED_0 + num_active) i = waitcode-WAIT_ABANDONED_0; - else i = waitcode-WAIT_OBJECT_0; - if (GetExitCodeProcess(active_handles[i], &exitcode)) { - CloseHandle(active_handles[i]); - *status = (int)((exitcode & 0xff) << 8); - return (int)active_handles[i]; - } - } - -FAILED: - errno = GetLastError(); - return -1; -} - -# endif /* !__BORLANDC__ */ - - -# endif /* USE_EXECNT */ diff --git a/src/jam.c b/src/jam.c index 9768efb..b522376 100644 --- a/src/jam.c +++ b/src/jam.c @@ -66,8 +66,7 @@ * builtins.c - jam's built-in rules * command.c - maintain lists of commands * compile.c - compile parsed jam statements - * execunix.c - execute a shell script on UNIX - * execvms.c - execute a shell script, ala VMS + * execcmd.c - execute a shell script on UNIX * expand.c - expand a buffer, given variable values * file*.c - scan directories and archives on * * hash.c - simple in-memory hashing routines diff --git a/src/jam.h b/src/jam.h index 1d70507..1557795 100644 --- a/src/jam.h +++ b/src/jam.h @@ -57,7 +57,6 @@ # define OS_NT # define SPLITPATH ';' # define MAXLINE 2046 /* longest 'together' actions */ -# define USE_EXECUNIX # define USE_PATHUNIX /*# define USE_EXECNT*/ # define PATH_DELIM '\\' @@ -82,7 +81,6 @@ # define OS_NT # define SPLITPATH ';' # define MAXLINE 996 /* longest 'together' actions */ -# define USE_EXECUNIX # define USE_PATHUNIX # define PATH_DELIM '\\' # define DOWNSHIFT_PATHS @@ -92,7 +90,6 @@ /* God fearing UNIX */ #ifndef OSMINOR # define OSMAJOR "UNIX=true" -# define USE_EXECUNIX # define USE_FILEUNIX # define USE_PATHUNIX # define PATH_DELIM '/' -- 2.11.4.GIT