⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 execunix.c

📁 jam源码
💻 C
字号:
/* * Copyright 1993, 1995 Christopher Seiwald. * * This file is part of Jam - see jam.c for Copyright information. *//* * execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS * * If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp(). * The default is: * *	/bin/sh -c %		[ on UNIX/AmigaOS ] *	cmd.exe /c %		[ on OS2/WinNT ] * * 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 * 01/20/00 (seiwald) - Upgraded from K&R to ANSI C * 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 <errno.h># ifdef USE_EXECUNIX# ifdef OS_OS2# define USE_EXECNT# include <process.h># endif# ifdef OS_NT # define USE_EXECNT# include <process.h># define WIN32_LEAN_AND_MEAN# include <windows.h>		/* do the ugly deed */# define USE_MYWAIT# if !defined( __BORLANDC__ ) # define wait my_waitstatic int my_wait( int *status );# endif# endifstatic int intr = 0;static int cmdsrunning = 0;static void (*istat)( int );static struct{	int	pid; /* on win32, a real process handle */	void	(*func)( void *closure, int status );	void 	*closure;# ifdef USE_EXECNT	char	*tempfile;# endif} cmdtab[ MAXJOBS ] = {{0}};/* * onintr() - bump intr to note command interruption */voidonintr( int disp ){	intr++;	printf( "...interrupted\n" );}/* * execcmd() - launch an async command execution */voidexeccmd( 	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 );	}# 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%dt%d.bat", 				tempdir, GetCurrentProcessId(), slot );	}	/* 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( p && *p || strlen( string ) > MAXLINE || shell )	{	    FILE *f;	    /* 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). */	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	{# ifdef USE_EXECNT	    argv[0] = "cmd.exe";	    argv[1] = "/Q/C";		/* anything more is non-portable */# else	    argv[0] = "/bin/sh";	    argv[1] = "-c";# endif	    argv[2] = string;	    argv[3] = 0;	}	/* Catch interrupts whenever commands are running. */	if( !cmdsrunning++ )	    istat = signal( SIGINT, onintr );	/* Start the command */# ifdef USE_EXECNT	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], argv );	    _exit(127);	}# endif	if( pid == -1 )	{	    perror( "vfork" );	    exit( EXITBAD );	}# endif	/* 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 */intexecwait(){	int i;	int status, w;	int rstat;	/* Handle naive make1() which doesn't know if cmds are running. */	if( !cmdsrunning )	    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 );	}# ifdef USE_EXECNT	/* Clear the temp file */	unlink( cmdtab[ i ].tempfile );# endif	/* 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;}# ifdef USE_MYWAITstatic intmy_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 /* USE_MYWAIT */# endif /* USE_EXECUNIX */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -