home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* e x e c u t e . C */
- /* */
- /* Execute an external command for UUPC/extended functions */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Changes Copyright (c) 1989-1993 by Kendra Electronic */
- /* Wonderworks. */
- /* */
- /* All rights reserved except those explicitly granted by */
- /* the UUPC/extended license agreement. */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* RCS Information */
- /*--------------------------------------------------------------------*/
-
- /*
- * $Id: execute.c 1.11 1993/10/03 22:09:09 ahd Exp $
- *
- * Revision history:
- * $Log: execute.c $
- * Revision 1.11 1993/10/03 22:09:09 ahd
- * Change debugging messages
- *
- * Revision 1.10 1993/10/02 22:56:59 ahd
- * Suppress compile warning
- *
- * Revision 1.9 1993/10/02 19:07:49 ahd
- * Suppress compiler warning
- *
- * Revision 1.8 1993/09/27 00:45:20 ahd
- * Fix Windows compile, add debug to OS/2 and DOS version
- *
- * Revision 1.7 1993/09/26 03:32:27 dmwatt
- * Use Standard Windows NT error message module
- *
- * Revision 1.6 1993/09/23 03:26:51 ahd
- * Use common file search routine
- *
- * Revision 1.5 1993/09/20 04:38:11 ahd
- * TCP/IP support from Dave Watt
- * 't' protocol support
- * OS/2 2.x support
- *
- * Revision 1.4 1993/08/08 17:39:09 ahd
- * Denormalize path for opening on selected networks
- *
- * Revision 1.3 1993/08/03 03:11:49 ahd
- * Further Windows 3.x fixes
- *
- * Revision 1.2 1993/08/02 03:24:59 ahd
- * Further changes in support of Robert Denny's Windows 3.x support
- *
- * Revision 1.1 1993/07/31 16:22:16 ahd
- * Initial revision
- *
- */
-
- /*--------------------------------------------------------------------*/
- /* System include files */
- /*--------------------------------------------------------------------*/
-
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include <process.h>
- #include <io.h>
-
- #ifdef WIN32
- #include <windows.h>
- #include <signal.h>
- #elif defined(_Windows)
- #include <windows.h>
- #include <shellapi.h>
- #endif
-
- #include <direct.h>
-
- /*--------------------------------------------------------------------*/
- /* UUPC/extended include files */
- /*--------------------------------------------------------------------*/
-
- #include "lib.h"
- #include "hlib.h"
- #include "execute.h"
-
- #ifdef _Windows
- #include "winutil.h"
- #endif
-
- #ifdef WIN32
- #include "pnterr.h"
- #endif
-
- /*--------------------------------------------------------------------*/
- /* Local variables */
- /*--------------------------------------------------------------------*/
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* Internal function prototypes */
- /*--------------------------------------------------------------------*/
-
- static boolean internal( const char *command );
-
- static boolean batch( const char *input, char *output);
-
- #ifdef _Windows
-
- /*--------------------------------------------------------------------*/
- /* e x e c u t e (Windows 3.x version) */
- /* */
- /* execute external command under Windows */
- /*--------------------------------------------------------------------*/
-
- int execute( const char *command,
- const char *parameters,
- const char *input,
- const char *output,
- const boolean synchronous,
- const boolean foreground )
- {
- int result;
-
- boolean useBat = (input != NULL) || (output != NULL );
-
- char path[FILENAME_MAX]; /* String for executable file */
- char batchFile[FILENAME_MAX]; /* String for batch driver file */
- char perfect[FILENAME_MAX]; /* String for results test file */
-
- /*--------------------------------------------------------------------*/
- /* Locate the command */
- /*--------------------------------------------------------------------*/
-
- if ( internal( command ) )
- {
- strcpy( path , command );
- useBat = TRUE;
- }
- else if (batch( command, path ))
- {
- if (useBat) // Using redirection?
- {
- printmsg(0,"Cannot use redirection with batch file %s",
- path );
- return -2;
- }
- } /* else */
- else if ( !*path ) // Error returned from search?
- return -1; // Yes --> Error already reported
-
- /*--------------------------------------------------------------------*/
- /* Generate a batch file for redirected DOS programs, if needed */
- /*--------------------------------------------------------------------*/
-
- if ( useBat )
- {
- FILE *stream ;
-
- mktempname( batchFile, "BAT");
- mktempname( perfect, "TMP");
- stream = FOPEN( batchFile, "w", TEXT_MODE );
-
- if ( stream == NULL )
- {
- printerr( batchFile );
- panic();
- }
-
- fprintf( stream ,
- "@echo off\n%s %s",
- path,
- parameters == NULL ? "" : parameters );
-
- if ( input != NULL )
- fprintf( stream, " < %s", input );
-
- if ( output != NULL )
- fprintf( stream, " < %s", output );
-
- fprintf( stream,
- "\nif errorlevel 1 erase %s\n",
- perfect );
-
- fclose ( stream );
-
- stream = FOPEN( perfect, "w", TEXT_MODE );
- if ( stream == NULL )
- {
- printerr( perfect );
- panic();
- }
- fclose( stream );
-
- strcpy( path, batchFile ); // Run the batch command
-
- } /* if ( useBat ) */
-
- /*--------------------------------------------------------------------*/
- /* Actually run the command */
- /*--------------------------------------------------------------------*/
-
- result = SpawnWait( path,
- parameters,
- synchronous,
- foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE );
-
- /*--------------------------------------------------------------------*/
- /* For batch files, we can only report zero/non-zero */
- /* results. Do so, and clean up our input file at the same */
- /* time. */
- /*--------------------------------------------------------------------*/
-
- if ( useBat )
- {
- int unlinkResult = unlink( perfect );
-
- if (( result == 0 ) && (unlinkResult != 0))
- result = 255;
-
- if (unlink( batchFile ))
- printerr( batchFile );
-
- } /* if ( useBat ) */
-
- /*--------------------------------------------------------------------*/
- /* Report results of command */
- /*--------------------------------------------------------------------*/
-
- printmsg( 4,"Result of spawn %s is ... %d", command, result);
-
- return result;
-
- } /* execute */
-
- #elif defined(WIN32)
-
- /*--------------------------------------------------------------------*/
- /* e x e c u t e (Windows NT version) */
- /* */
- /* Execute an external program */
- /*--------------------------------------------------------------------*/
-
- int execute( const char *command,
- const char *parameters,
- const char *input,
- const char *output,
- const boolean synchronous,
- const boolean foreground )
- {
- int result;
- char path[BUFSIZ];
-
- /*--------------------------------------------------------------------*/
- /* Redirect STDIN and STDOUT as required */
- /*--------------------------------------------------------------------*/
-
- if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
- {
- printerr(input);
- return -2;
- }
-
- if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
- {
- printerr( output );
- if ( input != NULL )
- {
- FILE *temp = freopen("con", "rt", stdin);
-
- if ( (temp == NULL) && (errno != 0) )
- {
- printerr("stdin");
- panic();
- }
- setvbuf( stdin, NULL, _IONBF, 0);
-
- } /* if ( input != NULL ) */
- return -2;
- }
-
- /*--------------------------------------------------------------------*/
- /* Execute the command in question */
- /*--------------------------------------------------------------------*/
-
- if (internal(strcpy(path,command)) ||
- batch(command, path)) // Internal or batch command?
- {
-
- if ( parameters == NULL )
- result = system( path );
- else {
-
- strcat( path, " ");
- strcat( path, parameters );
-
- result = system( path );
-
- } /* else */
-
- } /* if (internal(command)) */
- else { /* No --> Invoke normally */
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- void *oldCtrlCHandler;
-
- if ( ! *path ) // Did search fail?
- return -2; // Yes --> Msg issued, just return
-
- memset(&si, 0, sizeof(STARTUPINFO));
- si.cb = sizeof(STARTUPINFO);
- si.lpTitle = (LPSTR)command;
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE;
-
-
- if (parameters != NULL)
- {
- strcat( path, " ");
- strcat( path, parameters );
- }
-
- result = CreateProcess(NULL,
- path,
- NULL,
- NULL,
- TRUE,
- 0,
- NULL,
- NULL,
- &si,
- &pi);
-
- if (!result) // Did CreateProcess() fail?
- { // Yes --> Report error
- DWORD dwError = GetLastError();
- printmsg(0, "execute: CreateProcess failed");
- printNTerror("CreateProcess", dwError);
- }
- else {
-
- if (synchronous)
- {
-
- /*--------------------------------------------------------------------*/
- /* Set things up so that we ignore Ctrl-C's coming in to the */
- /* child, and wait for other application to finish. */
- /*--------------------------------------------------------------------*/
-
- oldCtrlCHandler = signal(SIGINT, SIG_IGN);
-
- WaitForSingleObject(pi.hProcess, INFINITE);
- GetExitCodeProcess(pi.hProcess, &result);
-
- signal(SIGINT, oldCtrlCHandler); // Re-enable Ctrl-C handling
-
- } /* if (synchronous) */
- else
- result = 0;
-
- /*--------------------------------------------------------------------*/
- /* If we're spawning asynchronously, we assume that we don't */
- /* care about the exit code from the spawned process. */
- /* Closing these makes it impossible to get at the old */
- /* process's exit code. */
- /*--------------------------------------------------------------------*/
-
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
-
- } /* else !result */
-
- } /* else internal command */
-
- /*--------------------------------------------------------------------*/
- /* Re-open our standard i/o streams */
- /*--------------------------------------------------------------------*/
-
- if ( output != NULL )
- {
- freopen("con", "wt", stdout);
- setvbuf( stdout, NULL, _IONBF, 0);
- }
-
- if ( input != NULL )
- {
- FILE *temp = freopen("con", "rt", stdin);
-
- if ( (temp == NULL) && (errno != 0) )
- {
- printerr("stdin");
- panic();
- }
-
- setvbuf( stdin, NULL, _IONBF, 0);
-
- } /* if ( input != NULL ) */
-
- /*--------------------------------------------------------------------*/
- /* Report results of command */
- /*--------------------------------------------------------------------*/
-
- printmsg( 4 ,"Result of spawn %s is ... %d", command, result);
-
- return result;
-
- } /* execute */
-
- #else
-
- #ifdef __TURBOC__
- #pragma argsused
- #endif
-
- /*--------------------------------------------------------------------*/
- /* e x e c u t e (OS/2 + DOS version) */
- /* */
- /* Generic execute external command with optional redirection */
- /* of standard input and output */
- /*--------------------------------------------------------------------*/
-
- int execute( const char *command,
- const char *parameters,
- const char *input,
- const char *output,
- const boolean synchronous,
- const boolean foreground )
- {
- int result;
- char path[BUFSIZ];
-
- /*--------------------------------------------------------------------*/
- /* Redirect STDIN and STDOUT as required */
- /*--------------------------------------------------------------------*/
-
- if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
- {
- printerr(input);
- return -2;
- }
-
- if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
- {
- printerr( output );
- if ( input != NULL )
- {
- FILE *temp = freopen("con", "rt", stdin);
-
- if ( (temp == NULL) && (errno != 0) )
- {
- printerr("stdin");
- panic();
- }
- setvbuf( stdin, NULL, _IONBF, 0);
-
- } /* if ( input != NULL ) */
-
- return -2;
- }
-
- /*--------------------------------------------------------------------*/
- /* Execute the command in question */
- /*--------------------------------------------------------------------*/
-
- if (internal(strcpy(path,command)) ||
- batch(command,path)) // Internal command or batch file?
- {
-
- if ( parameters == NULL )
- result = system( path );
- else {
-
- strcat( path, " ");
- strcat( path, parameters );
-
- result = system( path );
- } /* else */
-
- } /* if (internal(command)) */
- else { /* No --> Invoke normally */
-
- if ( *path )
- {
- printmsg(4,"execute: spawnlp(%d, %s, %s%s%s)",
- synchronous ? P_WAIT : P_NOWAIT,
- path,
- command,
- parameters == NULL ? "" : ", ",
- parameters == NULL ? "" : parameters );
-
- result = spawnlp( synchronous ? P_WAIT : P_NOWAIT,
- (char *) path,
- (char *) command,
- (char *) parameters,
- NULL);
-
- if (result == -1) /* Did spawn fail? */
- printerr(command); /* Yes --> Report error */
- } /* else */
- else
- result = -3; // Flag we never ran command
-
- } /* else */
-
- /*--------------------------------------------------------------------*/
- /* Re-open our standard i/o streams */
- /*--------------------------------------------------------------------*/
-
- if ( output != NULL )
- {
- freopen("con", "wt", stdout);
- setvbuf( stdout, NULL, _IONBF, 0);
- }
-
- if ( input != NULL )
- {
- FILE *temp = freopen("con", "rt", stdin);
-
- if ( (temp == NULL) && (errno != 0) )
- {
- printerr("stdin");
- panic();
- }
- setvbuf( stdin, NULL, _IONBF, 0);
-
- } /* if ( input != NULL ) */
-
- /*--------------------------------------------------------------------*/
- /* Report results of command */
- /*--------------------------------------------------------------------*/
-
- printmsg( 4,"Result of spawn %s is ... %d", command, result);
-
- return result;
-
- } /* execute */
-
- #endif
-
- /*--------------------------------------------------------------------*/
- /* e x e c u t e C o m m a n d */
- /* */
- /* Split command from its parameters for execute */
- /*--------------------------------------------------------------------*/
-
- int executeCommand( const char *command,
- const char *input,
- const char *output,
- const boolean synchronous,
- const boolean foreground )
- {
- char *cmdname;
- char *parameters;
- char buffer[FILENAME_MAX];
- int result;
-
- strcpy( buffer, command );
-
- cmdname = strtok( buffer, WHITESPACE );
- parameters = strtok( NULL, "\r\n" );
-
- if ( parameters != NULL )
- {
- while (isspace( *parameters ) || iscntrl( *parameters ))
- parameters++;
-
- if ( !strlen( parameters ))
- parameters = NULL;
- }
-
- result = execute( cmdname,
- parameters,
- input,
- output,
- synchronous,
- foreground );
-
- return result;
-
- } /* executeCommand */
-
- /*--------------------------------------------------------------------*/
- /* i n t e r n a l */
- /* */
- /* Determine if command is internal DOS command */
- /*--------------------------------------------------------------------*/
-
- static boolean internal( const char *command )
- {
- static char *commands[] = { "break", "cd", "chdir", "copy",
- "ctty", "date", "del", "dir",
- "echo", "erase", "for", "md",
- "mkdir", "rd", "rem", "ren",
- "rename", "rmdir", "time", "ver",
- "verify", "vol",
- NULL };
- char **list;
-
- /*--------------------------------------------------------------------*/
- /* Determine command list to use */
- /*--------------------------------------------------------------------*/
-
- if (E_internal == NULL )
- list = commands;
- else
- list = E_internal;
-
- /*--------------------------------------------------------------------*/
- /* Scan the list for the command */
- /*--------------------------------------------------------------------*/
-
- while( *list != NULL )
- {
- printmsg(5,"Searching for \"%s\", comparing to \"%s\"",
- *list, command);
-
- if (equali(*list++,command))
- {
- printmsg(4,"\"%s\" is an internal command",command);
- return TRUE;
- } /* if */
-
- } /* while( *list != NULL ) */
-
- /*--------------------------------------------------------------------*/
- /* The command is not in the list; return FALSE (external */
- /* command) */
- /*--------------------------------------------------------------------*/
-
- printmsg(4,"\"%s\" is an external command",command);
- return FALSE;
-
- } /* internal */
-
- /*--------------------------------------------------------------------*/
- /* b a t c h */
- /* */
- /* Determine if a command is batch file */
- /*--------------------------------------------------------------------*/
-
- static boolean batch( const char *input, char *output)
- {
- char *search = getenv("PATH");
- char *gotPath;
- char *period;
-
- static const char *extensions[] = { ".exe",
- ".com",
- #if !defined(_DOS) && !defined(_Windows)
- ".cmd",
- #endif
- ".bat",
- NULL };
-
- /*--------------------------------------------------------------------*/
- /* Validate the search path exists */
- /*--------------------------------------------------------------------*/
-
- if ( search == NULL )
- {
- printmsg(0,"batch: Unable to retrieve PATH environment variable!");
- panic();
- }
-
- /*--------------------------------------------------------------------*/
- /* Determine if we have path, and if we have an extension */
- /*--------------------------------------------------------------------*/
-
- gotPath = strchr( input, '/');
- if ( gotPath == NULL )
- gotPath = strchr( input, '\\');
-
- period = strchr( (gotPath == NULL) ? input : gotPath, '.');
-
- if ( period != NULL ) // We have extension?
- {
- if ( gotPath ) // Extension + path?
- { // Yes --> Just look for the file
-
- char *fname = normalize( input );
-
- if ( access( input, 00))
- *output = '\0';
- else
- strcpy( output, fname );
-
- } /* if ( gotPath ) */
- else
- _searchenv( input, "PATH", output );
-
- if ( ! *output ) // No file found?
- {
-
- printerr( input );
- return FALSE;
-
- } /* if ( ! *output ) */
-
- #if defined(_DOS) || defined(_Windows)
- return equal( period, ".bat" );
- #else
- return equali( period, ".cmd" ) || equali( period, ".bat" );
- #endif
-
- } /* if ( p != NULL ) */
-
- /*--------------------------------------------------------------------*/
- /* Walk the path looking for the file's possible types in */
- /* the path's directories */
- /*--------------------------------------------------------------------*/
-
- while( *search )
- {
- char base[FILENAME_MAX];
- int extension = 0;
-
- if ( gotPath )
- {
- strcpy( base, input );
- search = ""; // Force this to be last pass
- }
- else {
-
- char *next = strchr(search,';'); // Find next path component
- size_t len;
-
- if ( next == NULL )
- len = strlen( search );
- else
- len = (size_t) (next - search);
-
- memcpy( base, search, len ); // Path for search ...
- search += len + 1; // Step past semicolon
- if ( base[len - 1 ] != '\\' ) // Ending in back slash?
- base[len++] = '\\'; // No --> Add one
- strcpy( base + len , input ); // ... plus file name
-
- } /* else */
-
- printmsg(8,
- "Searching for extension of %s",
- base );
-
- /*--------------------------------------------------------------------*/
- /* Search a single directory in a path for a file with */
- /* various extensions. */
- /*--------------------------------------------------------------------*/
-
- while( extensions[extension] != NULL )
- {
- strcpy( output, base );
- strcat( output, extensions[extension] );
-
- if ( ! access(output, 00 ))
- {
-
- #if defined(_DOS) || defined(_Windows)
- return equal( extensions[extension] , ".bat" );
- #else
- return equal( extensions[extension] , ".cmd" ) ||
- equal( extensions[extension] , ".bat" );
- #endif
- } /* if ( result != NULL ) */
-
- extension++;
-
- } /* while( extensions[extension] != NULL ) */
-
- } /* while( *search ) */
-
- /*--------------------------------------------------------------------*/
- /* We could not find the file, report failure to the caller */
- /*--------------------------------------------------------------------*/
-
- printmsg(0, "batch: Unable to locate %s in search path", input);
-
- *output = '\0'; // Flag no file found!
- return FALSE;
-
- } /* batch */
-