2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 01:12:13 +00:00

Code cleanup in Boost Jam's execnt.c module.

[SVN r79041]
This commit is contained in:
Jurko Gospodnetić
2012-06-24 00:09:46 +00:00
parent 311d9a29d2
commit 2c7252a773
2 changed files with 90 additions and 87 deletions

View File

@@ -16,6 +16,7 @@
#ifndef EXECCMD_H
#define EXECCMD_H
#include "lists.h"
#include "strings.h"
#include <time.h>

View File

@@ -12,16 +12,18 @@
*/
#include "jam.h"
#include "lists.h"
#include "execcmd.h"
#include "lists.h"
#include "output.h"
#include "pathsys.h"
#include "string.h"
#include "output.h"
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#ifdef USE_EXECNT
@@ -33,31 +35,21 @@
/*
* execnt.c - execute a shell command on Windows NT
*
* If $(JAMSHELL) is defined, uses that to formulate the actual command.
* 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.
* If $(JAMSHELL) is defined, uses that to formulate the actual command. The
* default is: cmd.exe /Q/C
*
* In $(JAMSHELL), % expands to the command string and ! expands to the slot
* number (starting at 1) for multiprocess (-j) invocations. If $(JAMSHELL) does
* not include a %, it is tacked on as the last argument.
*
* Do not just set JAMSHELL to /bin/sh or cmd.exe - it will not work!
* Each $(JAMSHELL) placeholder must be specified as a separate individual
* element in a jam variable value.
*
* Do not just set JAMSHELL to cmd.exe - it will not work!
*
* External routines:
* exec_cmd() - launch an async command execution.
* exec_wait() - 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
* exec_wait() - wait for any of the async command processes to terminate.
*/
/* get the maximum shell command line length according to the OS */
@@ -73,7 +65,9 @@ static long can_spawn( string * pCommand );
static FILETIME add_64(
unsigned long h1, unsigned long l1,
unsigned long h2, unsigned long l2 );
/* */
static FILETIME add_FILETIME( FILETIME t1, FILETIME t2 );
/* */
static FILETIME negate_FILETIME( FILETIME t );
/* convert a FILETIME to a number of seconds */
static double filetime_seconds( FILETIME t );
@@ -93,12 +87,14 @@ static void read_output();
static int try_kill_one();
/* */
static double creation_time( HANDLE );
/* is the first process a parent (direct or indirect) to second one */
/* is the first process a parent (direct or indirect) to the second one */
static int is_parent_child( DWORD, DWORD );
/* */
static void close_alert( HANDLE );
/* close any alerts hanging around */
static void close_alerts();
/* returns a string's value buffer if not empty or 0 if empty */
static char const * null_if_empty( string const * str );
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -110,11 +106,11 @@ static void (* istat)( int );
/* The list of commands we run. */
static struct
{
string action; /* buffer to hold action */
string target; /* buffer to hold target */
string command; /* buffer to hold command being invoked */
string action[ 1 ]; /* buffer to hold action */
string target[ 1 ]; /* buffer to hold target */
string command[ 1 ]; /* buffer to hold command being invoked */
/* Temporary batch file used to execute the action when needed. */
/* Temporary command file used to execute the action when needed. */
char * tempfile_bat;
/* Pipes for communicating with the child process. Parent reads from (0),
@@ -123,12 +119,12 @@ static struct
HANDLE pipe_out[ 2 ];
HANDLE pipe_err[ 2 ];
string buffer_out; /* buffer to hold stdout, if any */
string buffer_err; /* buffer to hold stderr, if any */
string buffer_out[ 1 ]; /* buffer to hold stdout, if any */
string buffer_err[ 1 ]; /* buffer to hold stderr, if any */
PROCESS_INFORMATION pi; /* running process information */
DWORD exit_code; /* executed command's exit code */
int exit_reason; /* reason why a command completed */
PROCESS_INFORMATION pi; /* running process information */
DWORD exit_code; /* executed command's exit code */
int exit_reason; /* reason why a command completed */
/* Function called when the command completes. */
ExecCmdCallback func;
@@ -169,14 +165,14 @@ void execnt_unit_test()
}
{
string long_command;
string_new( &long_command );
string_reserve( &long_command, MAXLINE + 10 );
long_command.size = long_command.capacity - 1;
memset( long_command.value, 'x', long_command.size );
long_command.value[ long_command.size ] = 0;
assert( can_spawn( &long_command ) == MAXLINE + 9 );
string_free( &long_command );
string long_command[ 1 ];
string_new( long_command );
string_reserve( long_command, MAXLINE + 10 );
long_command->size = long_command->capacity - 1;
memset( long_command->value, 'x', long_command->size );
long_command->value[ long_command->size ] = 0;
assert( can_spawn( long_command ) == MAXLINE + 9 );
string_free( long_command );
}
#endif
}
@@ -198,7 +194,7 @@ void exec_cmd
{
int slot;
int raw_cmd = 0 ;
string command_local;
string cmd_local[ 1 ];
/* Find a free slot in the running commands table. */
for ( slot = 0; slot < MAXJOBS; ++slot )
@@ -211,7 +207,7 @@ void exec_cmd
}
/* Trim all leading and trailing leading whitespace. */
string_new_trimmed( &command_local, pCommand_orig );
string_new_trimmed( cmd_local, pCommand_orig );
/* Check to see if we need to hack around the line-length limitation. Look
* for a JAMSHELL setting of "%", indicating that the command should be
@@ -226,7 +222,7 @@ void exec_cmd
* directly if it satisfies all the spawnability criteria or using a
* batch file and the default shell if not.
*/
raw_cmd = can_spawn( &command_local ) >= MAXLINE;
raw_cmd = can_spawn( cmd_local ) >= MAXLINE;
shell = L0;
}
@@ -270,7 +266,7 @@ void exec_cmd
printf( "failed to write command file!\n" );
exit( EXITBAD );
}
fputs( command_local.value, f );
fputs( cmd_local->value, f );
fclose( f );
if ( DEBUG_EXECCMD )
@@ -283,8 +279,8 @@ void exec_cmd
}
/* If we are running a command directly, we already have it prepared in
* command_local. Now prepare the final command-string to execute in case we
* are using a shell. If a custom shell was defined, be prepared for % and !
* cmd_local. Now prepare the final command-string to execute in case we are
* using a shell. If a custom shell was defined, be prepared for % and !
* subs. Otherwise, use stock cmd.exe.
*/
if ( !raw_cmd )
@@ -342,12 +338,12 @@ void exec_cmd
/* Put together the final command string we are to run. */
{
char const * * argp = argv;
string_truncate( &command_local, 0 );
string_append( &command_local, *(argp++) );
string_truncate( cmd_local, 0 );
string_append( cmd_local, *(argp++) );
while ( *argp )
{
string_push_back( &command_local, ' ' );
string_append( &command_local, *(argp++) );
string_push_back( cmd_local, ' ' );
string_append( cmd_local, *(argp++) );
}
}
}
@@ -429,46 +425,46 @@ void exec_cmd
cmdtab[ slot ].closure = closure;
if ( action && target )
{
string_free( &cmdtab[ slot ].action );
string_copy( &cmdtab[ slot ].action, action );
string_free( &cmdtab[ slot ].target );
string_copy( &cmdtab[ slot ].target, target );
string_free( cmdtab[ slot ].action );
string_copy( cmdtab[ slot ].action, action );
string_free( cmdtab[ slot ].target );
string_copy( cmdtab[ slot ].target, target );
}
else
{
string_free( &cmdtab[ slot ].action );
string_new ( &cmdtab[ slot ].action );
string_free( &cmdtab[ slot ].target );
string_new ( &cmdtab[ slot ].target );
string_free( cmdtab[ slot ].action );
string_new ( cmdtab[ slot ].action );
string_free( cmdtab[ slot ].target );
string_new ( cmdtab[ slot ].target );
}
string_copy( &cmdtab[ slot ].command, pCommand_orig->value );
string_copy( cmdtab[ slot ].command, pCommand_orig->value );
/* CreateProcessA() Windows API places a limit of 32768 characters
* (bytes) on the allowed command-line length, including a trailing
* Unicode (2-byte) nul-terminator character.
*/
#define MAX_RAW_COMMAND_LENGTH 32766
if ( command_local.size > MAX_RAW_COMMAND_LENGTH )
if ( cmd_local->size > MAX_RAW_COMMAND_LENGTH )
{
printf( "Command line too long (%d characters). Maximum executable "
"command-line length is %d.", command_local.size,
"command-line length is %d.", cmd_local->size,
MAX_RAW_COMMAND_LENGTH );
exit( EXITBAD );
}
/* Create output buffers. */
string_new( &cmdtab[ slot ].buffer_out );
string_new( &cmdtab[ slot ].buffer_err );
string_new( cmdtab[ slot ].buffer_out );
string_new( cmdtab[ slot ].buffer_err );
if ( DEBUG_EXECCMD )
printf( "Command string to be sent to CreateProcessA(): '%s'\n",
command_local.value );
cmd_local->value );
/* Run the command by creating a sub-process for it. */
if (
!CreateProcessA(
NULL , /* application name */
command_local.value , /* command line */
cmd_local->value , /* command line */
NULL , /* process attributes */
NULL , /* thread attributes */
TRUE , /* inherit handles */
@@ -487,7 +483,7 @@ void exec_cmd
}
/* Free our local command string copy. */
string_free( &command_local );
string_free( cmd_local );
/* Wait until we are under the limit of concurrent commands. Do not trust
* globs.jobs alone.
@@ -560,35 +556,31 @@ int exec_wait()
/* Output the action block. */
out_action(
cmdtab[ i ].action.size > 0 ? cmdtab[ i ].action.value : 0,
cmdtab[ i ].target.size > 0 ? cmdtab[ i ].target.value : 0,
cmdtab[ i ].command.size > 0 ? cmdtab[ i ].command.value : 0,
cmdtab[ i ].buffer_out.size > 0 ? cmdtab[ i ].buffer_out.value : 0,
cmdtab[ i ].buffer_err.size > 0 ? cmdtab[ i ].buffer_err.value : 0,
null_if_empty( cmdtab[ i ].action ),
null_if_empty( cmdtab[ i ].target ),
null_if_empty( cmdtab[ i ].command ),
null_if_empty( cmdtab[ i ].buffer_out ),
null_if_empty( cmdtab[ i ].buffer_err ),
cmdtab[ i ].exit_reason );
/* Call the callback, may call back to jam rule land. Assume -p0 is in
* effect so only pass buffer containing merged output.
*/
(*cmdtab[ i ].func)(
cmdtab[ i ].closure,
rstat,
&time,
cmdtab[ i ].command.value,
cmdtab[ i ].buffer_out.value );
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time,
cmdtab[ i ].command->value, cmdtab[ i ].buffer_out->value );
/* Clean up the command data, process, etc. */
string_free( &cmdtab[ i ].action ); string_new( &cmdtab[ i ].action );
string_free( &cmdtab[ i ].target ); string_new( &cmdtab[ i ].target );
string_free( &cmdtab[ i ].command ); string_new( &cmdtab[ i ].command );
string_free( cmdtab[ i ].action ); string_new( cmdtab[ i ].action );
string_free( cmdtab[ i ].target ); string_new( cmdtab[ i ].target );
string_free( cmdtab[ i ].command ); string_new( cmdtab[ i ].command );
if ( cmdtab[ i ].pi.hProcess ) { CloseHandle( cmdtab[ i ].pi.hProcess ); cmdtab[ i ].pi.hProcess = 0; }
if ( cmdtab[ i ].pi.hThread ) { CloseHandle( cmdtab[ i ].pi.hThread ); cmdtab[ i ].pi.hThread = 0; }
if ( cmdtab[ i ].pipe_out[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 0 ] ); cmdtab[ i ].pipe_out[ 0 ] = 0; }
if ( cmdtab[ i ].pipe_out[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 1 ] ); cmdtab[ i ].pipe_out[ 1 ] = 0; }
if ( cmdtab[ i ].pipe_err[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 0 ] ); cmdtab[ i ].pipe_err[ 0 ] = 0; }
if ( cmdtab[ i ].pipe_err[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 1 ] ); cmdtab[ i ].pipe_err[ 1 ] = 0; }
string_free( &cmdtab[ i ].buffer_out ); string_new( &cmdtab[ i ].buffer_out );
string_free( &cmdtab[ i ].buffer_err ); string_new( &cmdtab[ i ].buffer_err );
string_free( cmdtab[ i ].buffer_out ); string_new( cmdtab[ i ].buffer_out );
string_free( cmdtab[ i ].buffer_err ); string_new( cmdtab[ i ].buffer_err );
cmdtab[ i ].exit_code = 0;
cmdtab[ i ].exit_reason = EXIT_OK;
}
@@ -611,9 +603,9 @@ static int raw_maxline()
os_info.dwOSVersionInfoSize = sizeof( os_info );
GetVersionEx( &os_info );
if ( os_info.dwMajorVersion >= 5 ) return 8191; /* XP */
if ( os_info.dwMajorVersion == 4 ) return 2047; /* NT 4.x */
return 996; /* NT 3.5.1 */
if ( os_info.dwMajorVersion >= 5 ) return 8191; /* XP */
if ( os_info.dwMajorVersion == 4 ) return 2047; /* NT 4.x */
return 996; /* NT 3.5.1 */
}
int maxline()
@@ -874,10 +866,10 @@ static void read_output()
{
/* Read stdout data. */
if ( cmdtab[ i ].pipe_out[ 0 ] )
read_pipe( cmdtab[ i ].pipe_out[ 0 ], & cmdtab[ i ].buffer_out );
read_pipe( cmdtab[ i ].pipe_out[ 0 ], cmdtab[ i ].buffer_out );
/* Read stderr data. */
if ( cmdtab[ i ].pipe_err[ 0 ] )
read_pipe( cmdtab[ i ].pipe_err[ 0 ], & cmdtab[ i ].buffer_err );
read_pipe( cmdtab[ i ].pipe_err[ 0 ], cmdtab[ i ].buffer_err );
}
}
@@ -913,7 +905,7 @@ static int try_wait( int timeoutMillis )
if ( ( WAIT_OBJECT_0 <= wait_api_result ) &&
( wait_api_result < WAIT_OBJECT_0 + num_active ) )
{
/* Rerminated process detected - return its index. */
/* Terminated process detected - return its index. */
return active_procs[ wait_api_result - WAIT_OBJECT_0 ];
}
@@ -1249,6 +1241,16 @@ static void close_alert( HANDLE process )
}
/*
* Returns a string's value buffer if not empty or 0 if empty.
*/
static char const * null_if_empty( string const * str )
{
return str->size ? str->value : 0;
}
void exec_done( void )
{
}