home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES1.ZIP / LIB / execute.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-14  |  32.5 KB  |  1,025 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       e x e c u t e . C                                            */
  3. /*                                                                    */
  4. /*       Execute an external command for UUPC/extended functions      */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  9. /*       Wonderworks.                                                 */
  10. /*                                                                    */
  11. /*       All rights reserved except those explicitly granted by       */
  12. /*       the UUPC/extended license agreement.                         */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: execute.c 1.18 1993/11/14 20:51:37 ahd Exp $
  21.  *
  22.  *    Revision history:
  23.  *    $Log: execute.c $
  24.  * Revision 1.18  1993/11/14  20:51:37  ahd
  25.  * Correct Windows 3.1 compile error
  26.  *
  27.  * Revision 1.17  1993/11/13  17:37:02  ahd
  28.  * Only use system() call for CMD files under OS/2
  29.  *
  30.  * Revision 1.16  1993/11/08  04:46:49  ahd
  31.  * Add OS/2 specific support for seperate sessions
  32.  *
  33.  * Revision 1.15  1993/11/06  17:54:55  rhg
  34.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  35.  *
  36.  * Revision 1.14  1993/10/30  17:10:40  rhg
  37.  * Correct direction of redirection for Windows batch files
  38.  *
  39.  * Revision 1.13  1993/10/12  00:43:34  ahd
  40.  * Normalize comments
  41.  *
  42.  * Revision 1.12  1993/10/09  15:46:15  rhg
  43.  * ANSIify the source
  44.  *
  45.  * Revision 1.11  1993/10/03  22:09:09  ahd
  46.  * Change debugging messages
  47.  *
  48.  * Revision 1.10  1993/10/02  22:56:59  ahd
  49.  * Suppress compile warning
  50.  *
  51.  * Revision 1.9  1993/10/02  19:07:49  ahd
  52.  * Suppress compiler warning
  53.  *
  54.  * Revision 1.8  1993/09/27  00:45:20  ahd
  55.  * Fix Windows compile, add debug to OS/2 and DOS version
  56.  *
  57.  * Revision 1.7  1993/09/26  03:32:27  dmwatt
  58.  * Use Standard Windows NT error message module
  59.  *
  60.  * Revision 1.6  1993/09/23  03:26:51  ahd
  61.  * Use common file search routine
  62.  *
  63.  * Revision 1.5  1993/09/20  04:38:11  ahd
  64.  * TCP/IP support from Dave Watt
  65.  * 't' protocol support
  66.  * OS/2 2.x support
  67.  *
  68.  * Revision 1.4  1993/08/08  17:39:09  ahd
  69.  * Denormalize path for opening on selected networks
  70.  *
  71.  * Revision 1.3  1993/08/03  03:11:49  ahd
  72.  * Further Windows 3.x fixes
  73.  *
  74.  * Revision 1.2  1993/08/02  03:24:59  ahd
  75.  * Further changes in support of Robert Denny's Windows 3.x support
  76.  *
  77.  * Revision 1.1  1993/07/31  16:22:16  ahd
  78.  * Initial revision
  79.  *
  80.  */
  81.  
  82. /*--------------------------------------------------------------------*/
  83. /*                        System include files                        */
  84. /*--------------------------------------------------------------------*/
  85.  
  86. #include <errno.h>
  87. #include <stdio.h>
  88. #include <stdlib.h>
  89. #include <string.h>
  90. #include <ctype.h>
  91. #include <time.h>
  92. #include <process.h>
  93. #include <io.h>
  94.  
  95. #ifdef WIN32
  96. #include <windows.h>
  97. #elif defined(WIN32)
  98. #include <windows.h>
  99. #include <signal.h>
  100. #elif defined(__OS2__) || defined(FAMILYAPI)
  101. #define INCL_DOSSESMGR
  102. #define INCL_DOSQUEUES
  103. #define INCL_NOPM
  104. #include <os2.h>
  105. #endif
  106.  
  107. #include <direct.h>
  108.  
  109. /*--------------------------------------------------------------------*/
  110. /*                    UUPC/extended include files                     */
  111. /*--------------------------------------------------------------------*/
  112.  
  113. #include "lib.h"
  114. #include "hlib.h"
  115. #include "execute.h"
  116.  
  117. #ifdef _Windows
  118. #include <windows.h>
  119. #include "winutil.h"
  120. #elif defined(WIN32)
  121. #include "pnterr.h"
  122. #elif defined(__OS2__) || defined(FAMILYAPI)
  123. #include "pos2err.h"
  124. #endif
  125.  
  126. /*--------------------------------------------------------------------*/
  127. /*                          Local variables                           */
  128. /*--------------------------------------------------------------------*/
  129.  
  130. currentfile();
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*                    Internal function prototypes                    */
  134. /*--------------------------------------------------------------------*/
  135.  
  136. static boolean internal( const char *command );
  137.  
  138. static boolean batch( const char *input, char *output);
  139.  
  140. #if defined(__OS2__) || defined(FAMILYAPI)
  141.  
  142. static int executeAsync( const char *command,
  143.                          const char *parameters,
  144.                          const boolean synchronous,
  145.                          const boolean foreground );
  146. #endif
  147.  
  148. #ifdef _Windows
  149.  
  150. /*--------------------------------------------------------------------*/
  151. /*       e x e c u t e                       (Windows 3.x version)    */
  152. /*                                                                    */
  153. /*       execute external command under Windows                       */
  154. /*--------------------------------------------------------------------*/
  155.  
  156. int execute( const char *command,
  157.              const char *parameters,
  158.              const char *input,
  159.              const char *output,
  160.              const boolean synchronous,
  161.              const boolean foreground )
  162. {
  163.    int result;
  164.  
  165.    boolean useBat = (input != NULL) || (output != NULL );
  166.  
  167.    char path[FILENAME_MAX];         /* String for executable file   */
  168.    char batchFile[FILENAME_MAX];    /* String for batch driver file */
  169.    char perfect[FILENAME_MAX];      /* String for results test file */
  170.  
  171. /*--------------------------------------------------------------------*/
  172. /*                    Validate command redirection                    */
  173. /*--------------------------------------------------------------------*/
  174.  
  175.    if ( ((input != NULL) || (output != NULL)) && ! synchronous )
  176.    {
  177.       printmsg(0, "execute: Internal error, cannot redirect asynchronous"
  178.                   " command %s",
  179.                  command );
  180.       panic();
  181.    }
  182.  
  183. /*--------------------------------------------------------------------*/
  184. /*                          Locate the command                        */
  185. /*--------------------------------------------------------------------*/
  186.  
  187.    if ( internal( command ) )
  188.    {
  189.       strcpy( path , command );
  190.       useBat = TRUE;
  191.    }
  192.    else if (batch( command, path ))
  193.    {
  194.       if (useBat)                      /* Using redirection?          */
  195.       {
  196.          printmsg(0,"Cannot use redirection with batch file %s",
  197.                      path );
  198.          return -2;
  199.       }
  200.    } /* else */
  201.    else if ( !*path )                  /* Error returned from search? */
  202.       return -1;                       /* Yes --> Error already reported */
  203.  
  204. /*--------------------------------------------------------------------*/
  205. /*     Generate a batch file for redirected DOS programs, if needed   */
  206. /*--------------------------------------------------------------------*/
  207.  
  208.    if ( useBat )
  209.    {
  210.       FILE *stream ;
  211.  
  212.       mktempname( batchFile, "BAT");
  213.       mktempname( perfect, "TMP");
  214.       stream = FOPEN( batchFile, "w", TEXT_MODE );
  215.  
  216.       if ( stream == NULL )
  217.       {
  218.          printerr( batchFile );
  219.          panic();
  220.       }
  221.  
  222.       fprintf( stream ,
  223.                "@echo off\n%s %s",
  224.                path,
  225.                parameters == NULL ? "" : parameters );
  226.  
  227.       if ( input != NULL )
  228.          fprintf( stream, " < %s", input );
  229.  
  230.       if ( output != NULL )
  231.          fprintf( stream, " > %s", output );
  232.  
  233.       fprintf( stream,
  234.               "\nif errorlevel 1 erase %s\n",
  235.                perfect );
  236.  
  237.       fclose ( stream );
  238.  
  239.       stream = FOPEN( perfect, "w", TEXT_MODE );
  240.       if ( stream == NULL )
  241.       {
  242.          printerr( perfect );
  243.          panic();
  244.       }
  245.       fclose( stream );
  246.  
  247.       strcpy( path, batchFile );             /* Run the batch command */
  248.  
  249.    } /* if ( useBat ) */
  250.  
  251. /*--------------------------------------------------------------------*/
  252. /*                       Actually run the command                     */
  253. /*--------------------------------------------------------------------*/
  254.  
  255.    result = SpawnWait( path,
  256.                        parameters,
  257.                        synchronous,
  258.                        foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE );
  259.  
  260. /*--------------------------------------------------------------------*/
  261. /*       For batch files, we can only report zero/non-zero            */
  262. /*       results.  Do so, and clean up our input file at the same     */
  263. /*       time.                                                        */
  264. /*--------------------------------------------------------------------*/
  265.  
  266.    if ( useBat )
  267.    {
  268.       int unlinkResult = unlink( perfect );
  269.  
  270.       if (( result == 0 ) && (unlinkResult != 0))
  271.          result = 255;
  272.  
  273.       if (unlink( batchFile ))
  274.          printerr( batchFile );
  275.  
  276.    } /* if ( useBat ) */
  277.  
  278. /*--------------------------------------------------------------------*/
  279. /*                     Report results of command                      */
  280. /*--------------------------------------------------------------------*/
  281.  
  282.    printmsg( 4,"Result of spawn %s is ... %d", command, result);
  283.  
  284.    return result;
  285.  
  286. } /* execute */
  287.  
  288. #elif defined(WIN32)
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*    e x e c u t e                             (Windows NT version)  */
  292. /*                                                                    */
  293. /*    Execute an external program                                     */
  294. /*--------------------------------------------------------------------*/
  295.  
  296. int execute( const char *command,
  297.              const char *parameters,
  298.              const char *input,
  299.              const char *output,
  300.              const boolean synchronous,
  301.              const boolean foreground )
  302. {
  303.    int result;
  304.    char path[BUFSIZ];
  305.  
  306. /*--------------------------------------------------------------------*/
  307. /*                    Validate command redirection                    */
  308. /*--------------------------------------------------------------------*/
  309.  
  310.    if ( ((input != NULL) || (output != NULL)) && ! synchronous )
  311.    {
  312.       printerr( "execute: Internal error, cannot redirect asynchronous command %s",
  313.                  command );
  314.       panic();
  315.    }
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*               Redirect STDIN and STDOUT as required                */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
  322.    {
  323.       printerr(input);
  324.       return -2;
  325.    }
  326.  
  327.    if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
  328.    {
  329.       printerr( output );
  330.       if ( input != NULL )
  331.       {
  332.          FILE *temp = freopen("con", "rt", stdin);
  333.  
  334.          if ( (temp == NULL) && (errno != 0) )
  335.          {
  336.             printerr("stdin");
  337.             panic();
  338.          }
  339.          setvbuf( stdin, NULL, _IONBF, 0);
  340.  
  341.       } /* if ( input != NULL ) */
  342.       return -2;
  343.    }
  344.  
  345. /*--------------------------------------------------------------------*/
  346. /*                  Execute the command in question                   */
  347. /*--------------------------------------------------------------------*/
  348.  
  349.    strcpy(path, command);
  350.  
  351.    if (internal(path) ||
  352.        batch(command, path))        /* Internal or batch command?     */
  353.    {
  354.  
  355.       if ( parameters == NULL )
  356.          result = system( path );
  357.       else {
  358.  
  359.          strcat( path, " ");
  360.          strcat( path, parameters );
  361.  
  362.          result = system( path );
  363.  
  364.       } /* else */
  365.  
  366.    } /* if (internal(command)) */
  367.    else  {                       /* No --> Invoke normally            */
  368.       STARTUPINFO si;
  369.       PROCESS_INFORMATION pi;
  370.       void *oldCtrlCHandler;
  371.  
  372.       if ( ! *path )                /* Did search fail?               */
  373.          return -2;                 /* Yes --> Msg issued, just return */
  374.  
  375.       memset(&si, 0, sizeof(STARTUPINFO));
  376.       si.cb = sizeof(STARTUPINFO);
  377.       si.lpTitle = (LPSTR)command;
  378.       si.dwFlags = STARTF_USESHOWWINDOW;
  379.       si.wShowWindow = foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE;
  380.  
  381.       if (parameters != NULL)
  382.       {
  383.          strcat( path, " ");
  384.          strcat( path, parameters );
  385.       }
  386.  
  387.       result = CreateProcess(NULL,
  388.                              path,
  389.                              NULL,
  390.                              NULL,
  391.                              TRUE,
  392.                              0,
  393.                              NULL,
  394.                              NULL,
  395.                              &si,
  396.                              &pi);
  397.  
  398.       if (!result)                  /* Did CreateProcess() fail?      */
  399.       {                             /* Yes --> Report error           */
  400.          DWORD dwError = GetLastError();
  401.          printmsg(0, "execute:  CreateProcess failed");
  402.          printNTerror("CreateProcess", dwError);
  403.       }
  404.       else {
  405.  
  406.          if (synchronous)
  407.          {
  408.  
  409. /*--------------------------------------------------------------------*/
  410. /*       Set things up so that we ignore Ctrl-C's coming in to the    */
  411. /*       child, and wait for other application to finish.             */
  412. /*--------------------------------------------------------------------*/
  413.  
  414.             oldCtrlCHandler = signal(SIGINT, SIG_IGN);
  415.  
  416.             WaitForSingleObject(pi.hProcess, INFINITE);
  417.             GetExitCodeProcess(pi.hProcess, &result);
  418.  
  419.             signal(SIGINT, oldCtrlCHandler); /* Re-enable Ctrl-C handling */
  420.  
  421.          }  /* if (synchronous) */
  422.          else
  423.             result = 0;
  424.  
  425. /*--------------------------------------------------------------------*/
  426. /*       If we're spawning asynchronously, we assume that we don't    */
  427. /*       care about the exit code from the spawned process.           */
  428. /*       Closing these makes it impossible to get at the old          */
  429. /*       process's exit code.                                         */
  430. /*--------------------------------------------------------------------*/
  431.  
  432.          CloseHandle(pi.hProcess);
  433.          CloseHandle(pi.hThread);
  434.  
  435.       } /* else !result */
  436.  
  437.    } /* else internal command */
  438.  
  439. /*--------------------------------------------------------------------*/
  440. /*                  Re-open our standard i/o streams                  */
  441. /*--------------------------------------------------------------------*/
  442.  
  443.    if ( output != NULL )
  444.    {
  445.       freopen("con", "wt", stdout);
  446.       setvbuf( stdout, NULL, _IONBF, 0);
  447.    }
  448.  
  449.    if ( input != NULL )
  450.    {
  451.       FILE *temp = freopen("con", "rt", stdin);
  452.  
  453.       if ( (temp == NULL) && (errno != 0) )
  454.       {
  455.          printerr("stdin");
  456.          panic();
  457.       }
  458.  
  459.       setvbuf( stdin, NULL, _IONBF, 0);
  460.  
  461.    } /* if ( input != NULL ) */
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*                     Report results of command                      */
  465. /*--------------------------------------------------------------------*/
  466.  
  467.    printmsg( 4 ,"Result of spawn %s is ... %d", command, result);
  468.  
  469.    return result;
  470.  
  471. } /* execute */
  472.  
  473. #else
  474.  
  475. #if _MSC_VER >= 700
  476. #pragma warning(disable:4100)   /* suppress unref'ed formal param. warnings */
  477. #endif
  478.  
  479. /*--------------------------------------------------------------------*/
  480. /*       e x e c u t e                       (OS/2 + DOS version)     */
  481. /*                                                                    */
  482. /*       Generic execute external command with optional redirection   */
  483. /*       of standard input and output                                 */
  484. /*--------------------------------------------------------------------*/
  485.  
  486. int execute( const char *command,
  487.              const char *parameters,
  488.              const char *input,
  489.              const char *output,
  490.              const boolean synchronous,
  491.              const boolean foreground )
  492. {
  493.    int result;
  494.    char path[BUFSIZ];
  495.    boolean redirected;
  496.  
  497. /*--------------------------------------------------------------------*/
  498. /*               Redirect STDIN and STDOUT as required                */
  499. /*--------------------------------------------------------------------*/
  500.  
  501.    if ( (input != NULL) || (output != NULL) )
  502.    {
  503.       redirected = TRUE;
  504.  
  505.       if ( ! synchronous )
  506.       {
  507.          printmsg(0, "execute: Internal error, "
  508.                      "cannot redirect asynchronous command %s",
  509.                  command );
  510.          panic();
  511.  
  512.       } /* if ( ! synchronous ) */
  513.    }
  514.    else
  515.       redirected = FALSE;
  516.  
  517.    if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
  518.    {
  519.       printerr(input);
  520.       return -2;
  521.    }
  522.  
  523.    if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
  524.    {
  525.       printerr( output );
  526.       if ( input != NULL )
  527.       {
  528.          FILE *temp = freopen("con", "rt", stdin);
  529.  
  530.          if ( (temp == NULL) && (errno != 0) )
  531.          {
  532.             printerr("stdin");
  533.             panic();
  534.          }
  535.          setvbuf( stdin, NULL, _IONBF, 0);
  536.  
  537.       } /* if ( input != NULL ) */
  538.  
  539.       return -2;
  540.    }
  541.  
  542. /*--------------------------------------------------------------------*/
  543. /*                  Execute the command in question                   */
  544. /*--------------------------------------------------------------------*/
  545.  
  546.    strcpy(path, command);
  547.  
  548.    if (internal(path) ||
  549.        batch(command, path))        /* Internal command or batch file? */
  550.    {
  551.  
  552.       if ( parameters != NULL )
  553.       {
  554.          strcat( path, " ");
  555.          strcat( path, parameters );
  556.       }
  557.  
  558. #if defined(__OS2__) || defined(FAMILYAPI)
  559.       result = system( path );
  560. #else
  561.       result = system( path );
  562. #endif
  563.  
  564.    } /* if (internal(command)) */
  565.    else if ( ! *path )
  566.       result = -3;            /* Flag we never ran command         */
  567. #if defined(__OS2__) || defined(FAMILYAPI)
  568.    else if ((foreground && ! redirected) || ! synchronous)
  569.       result = executeAsync( path, parameters, synchronous, foreground );
  570. #endif
  571.    else {
  572.  
  573.       result = spawnlp( P_WAIT,
  574.                         (char *) path,
  575.                         (char *) command,
  576.                         (char *) parameters,
  577.                         NULL);
  578.  
  579.       if (result == -1)       /* Did spawn fail?                   */
  580.          printerr(command);   /* Yes --> Report error              */
  581.  
  582.    } /* else */
  583.  
  584. /*--------------------------------------------------------------------*/
  585. /*                  Re-open our standard i/o streams                  */
  586. /*--------------------------------------------------------------------*/
  587.  
  588.    if ( output != NULL )
  589.    {
  590.       freopen("con", "wt", stdout);
  591.       setvbuf( stdout, NULL, _IONBF, 0);
  592.    }
  593.  
  594.    if ( input != NULL )
  595.    {
  596.       FILE *temp = freopen("con", "rt", stdin);
  597.  
  598.       if ( (temp == NULL) && (errno != 0) )
  599.       {
  600.          printerr("stdin");
  601.          panic();
  602.       }
  603.       setvbuf( stdin, NULL, _IONBF, 0);
  604.  
  605.    } /* if ( input != NULL ) */
  606.  
  607. /*--------------------------------------------------------------------*/
  608. /*                     Report results of command                      */
  609. /*--------------------------------------------------------------------*/
  610.  
  611.    printmsg( 4,"Result of spawn %s is ... %d", command, result);
  612.  
  613.    return result;
  614.  
  615. } /* execute */
  616.  
  617. #if _MSC_VER >= 700
  618. #pragma warning(default:4100)   /* restore unref'ed formal param. warnings */
  619. #endif
  620.  
  621. #endif
  622.  
  623. /*--------------------------------------------------------------------*/
  624. /*       e x e c u t e C o m m a n d                                  */
  625. /*                                                                    */
  626. /*       Split command from its parameters for execute                */
  627. /*--------------------------------------------------------------------*/
  628.  
  629. int executeCommand( const char *command,
  630.                     const char *input,
  631.                     const char *output,
  632.                     const boolean synchronous,
  633.                     const boolean foreground )
  634. {
  635.    char *cmdname;
  636.    char *parameters;
  637.    char buffer[FILENAME_MAX];
  638.    int result;
  639.  
  640.    strcpy( buffer, command );
  641.  
  642.    cmdname = strtok( buffer, WHITESPACE );
  643.    parameters = strtok( NULL, "\r\n" );
  644.  
  645.    if ( parameters != NULL )
  646.    {
  647.       while (isspace( *parameters ) || iscntrl( *parameters ))
  648.          parameters++;
  649.  
  650.       if ( !strlen( parameters ))
  651.          parameters = NULL;
  652.    }
  653.  
  654.    result = execute( cmdname,
  655.                      parameters,
  656.                      input,
  657.                      output,
  658.                      synchronous,
  659.                      foreground );
  660.  
  661.    return result;
  662.  
  663. } /* executeCommand */
  664.  
  665. /*--------------------------------------------------------------------*/
  666. /*    i n t e r n a l                                                 */
  667. /*                                                                    */
  668. /*    Determine if command is internal DOS command                    */
  669. /*--------------------------------------------------------------------*/
  670.  
  671. static boolean internal( const char *command )
  672. {
  673.    static char *commands[] = { "break",   "cd",    "chdir",    "copy",
  674.                                "ctty",    "date",  "del",      "dir",
  675.                                "echo",    "erase", "for",      "md",
  676.                                "mkdir",   "rd",    "rem",      "ren",
  677.                                "rename",  "rmdir", "time",     "ver",
  678.                                "verify",  "vol",
  679.                                NULL };
  680.    char **list;
  681.  
  682. /*--------------------------------------------------------------------*/
  683. /*                   Determine command list to use                    */
  684. /*--------------------------------------------------------------------*/
  685.  
  686.    if (E_internal == NULL )
  687.       list = commands;
  688.    else
  689.       list = E_internal;
  690.  
  691. /*--------------------------------------------------------------------*/
  692. /*                   Scan the list for the command                    */
  693. /*--------------------------------------------------------------------*/
  694.  
  695.    while( *list != NULL )
  696.    {
  697.       printmsg(5,"Searching for \"%s\", comparing to \"%s\"",
  698.                   *list, command);
  699.  
  700.       if (equali(*list++,command))
  701.       {
  702.          printmsg(4,"\"%s\" is an internal command",command);
  703.          return TRUE;
  704.       } /* if */
  705.  
  706.    } /* while( *list != NULL ) */
  707.  
  708. /*--------------------------------------------------------------------*/
  709. /*       The command is not in the list; return FALSE (external       */
  710. /*       command)                                                     */
  711. /*--------------------------------------------------------------------*/
  712.  
  713.    printmsg(4,"\"%s\" is an external command",command);
  714.    return FALSE;
  715.  
  716. } /* internal */
  717.  
  718. /*--------------------------------------------------------------------*/
  719. /*    b a t c h                                                       */
  720. /*                                                                    */
  721. /*    Determine if a command is batch file                            */
  722. /*--------------------------------------------------------------------*/
  723.  
  724. static boolean batch( const char *input, char *output)
  725. {
  726.    char *search = getenv("PATH");
  727.    char *gotPath;
  728.    char *period;
  729.  
  730.    static const char *extensions[] = { ".exe",
  731.                                        ".com",
  732. #if !defined(_DOS) && !defined(_Windows)
  733.                                        ".cmd",
  734. #endif
  735.                                        ".bat",
  736.                                        NULL };
  737.  
  738. /*--------------------------------------------------------------------*/
  739. /*                  Validate the search path exists                   */
  740. /*--------------------------------------------------------------------*/
  741.  
  742.    if ( search == NULL )
  743.    {
  744.       printmsg(0,"batch: Unable to retrieve PATH environment variable!");
  745.       panic();
  746.    }
  747.  
  748. /*--------------------------------------------------------------------*/
  749. /*        Determine if we have path, and if we have an extension      */
  750. /*--------------------------------------------------------------------*/
  751.  
  752.    gotPath = strchr( input, '/');
  753.    if ( gotPath == NULL )
  754.       gotPath = strchr( input, '\\');
  755.  
  756.    period = strchr( (gotPath == NULL) ? input : gotPath, '.');
  757.  
  758.    if ( period != NULL )         /*    We have extension?             */
  759.    {
  760.       if ( gotPath )             /* Extension + path?                 */
  761.       {                          /* Yes --> Just look for the file    */
  762.  
  763.          char *fname = normalize( input );
  764.  
  765.          if ( access( input, 00))
  766.             *output = '\0';
  767.          else
  768.             strcpy( output, fname );
  769.  
  770.       } /* if ( gotPath ) */
  771.       else
  772.          _searchenv( input, "PATH", output );
  773.  
  774.       if ( ! *output )           /* No file found?                    */
  775.       {
  776.  
  777.          printerr( input );
  778.          return FALSE;
  779.  
  780.       }  /* if ( ! *output ) */
  781.  
  782. #if defined(_DOS) || defined(_Windows)
  783.       return equal( period, ".bat" );
  784. #else
  785.       return equali( period, ".cmd" ) || equali( period, ".bat" );
  786. #endif
  787.  
  788.    } /* if ( p != NULL ) */
  789.  
  790. /*--------------------------------------------------------------------*/
  791. /*       Walk the path looking for the file's possible types in       */
  792. /*       the path's directories                                       */
  793. /*--------------------------------------------------------------------*/
  794.  
  795.    while( *search )
  796.    {
  797.       char base[FILENAME_MAX];
  798.       int extension = 0;
  799.  
  800.       if ( gotPath )
  801.       {
  802.          strcpy( base, input );
  803.          search = "";                        /* Force this to be last pass */
  804.       }
  805.       else {
  806.  
  807.          char *next = strchr(search,';');    /* Find next path component */
  808.          size_t len;
  809.  
  810.          if ( next == NULL )
  811.             len = strlen( search );
  812.          else
  813.             len = (size_t) (next - search);
  814.  
  815.          memcpy( base, search, len );        /* Path for search ...   */
  816.          search += len + 1;                  /* Step past semicolon   */
  817.          if ( base[len - 1 ] != '\\' )       /* Ending in back slash? */
  818.             base[len++] = '\\';              /* No --> Add one        */
  819.          strcpy( base + len , input );       /* ... plus file name    */
  820.  
  821.       } /* else */
  822.  
  823.       printmsg(8,
  824.                "Searching for extension of %s",
  825.                base );
  826.  
  827. /*--------------------------------------------------------------------*/
  828. /*       Search a single directory in a path for a file with          */
  829. /*       various extensions.                                          */
  830. /*--------------------------------------------------------------------*/
  831.  
  832.       while( extensions[extension] != NULL )
  833.       {
  834.          strcpy( output, base );
  835.          strcat( output, extensions[extension] );
  836.  
  837.          if ( ! access(output, 00 ))
  838.          {
  839.  
  840. #if defined(_DOS) || defined(_Windows)
  841.             return equal( extensions[extension] , ".bat" );
  842. #else
  843.             return equal( extensions[extension] , ".cmd" ) ||
  844.                    equal( extensions[extension] , ".bat" );
  845. #endif
  846.          } /* if ( result != NULL ) */
  847.  
  848.          extension++;
  849.  
  850.       }  /* while( extensions[extension] != NULL ) */
  851.  
  852.    } /* while( *search ) */
  853.  
  854. /*--------------------------------------------------------------------*/
  855. /*       We could not find the file, report failure to the caller     */
  856. /*--------------------------------------------------------------------*/
  857.  
  858.    printmsg(0, "batch: Unable to locate %s in search path", input);
  859.  
  860.    *output = '\0';                  /* Flag no file found!            */
  861.  
  862.    return FALSE;
  863.  
  864. } /* batch */
  865.  
  866. #if defined(__OS2__) || defined(FAMILYAPI)
  867.  
  868. /*--------------------------------------------------------------------*/
  869. /*       e x e c u t e A s y n c                                      */
  870. /*                                                                    */
  871. /*       Run a command in a new session under OS/2                    */
  872. /*--------------------------------------------------------------------*/
  873.  
  874. static int executeAsync( const char *command,
  875.                          const char *parameters,
  876.                          const boolean synchronous,
  877.                          const boolean foreground )
  878. {
  879.    STARTDATA sd;
  880.    PID   childPID;
  881.    static int instance = 0;      /* Number of program we've invoke   */
  882.  
  883.    char  queueName[FILENAME_MAX];
  884.    PVOID queueDataAddress;
  885.    BYTE  queueElementPriority;
  886.    HQUEUE queueHandle;
  887.  
  888. #ifdef __OS2__
  889.    APIRET rc;
  890.    REQUESTDATA  queueRequest;
  891.    ULONG sessID;
  892.    ULONG queueDataLength;
  893. #else
  894.    USHORT rc;
  895.    QUEUERESULT  queueRequest;
  896.    USHORT sessID;
  897.    USHORT queueDataLength;
  898.  
  899. #ifndef SSF_RELATED_CHILD
  900.  
  901.    #define SSF_RELATED_INDEPENDENT 0
  902.    #define SSF_RELATED_CHILD       1
  903.  
  904.    #define SSF_FGBG_FORE           0
  905.    #define SSF_FGBG_BACK           1
  906.  
  907.    #define SSF_TRACEOPT_NONE       0
  908.  
  909.    #define SSF_INHERTOPT_PARENT    1
  910.  
  911.    #define SSF_TYPE_DEFAULT        0
  912.  
  913.    #define SSF_CONTROL_MAXIMIZE    0x0002
  914.    #define SSF_CONTROL_MINIMIZE    0x0004
  915.  
  916. #endif  /* SSF_RELATED_CHILD */
  917. #endif
  918.  
  919. /*--------------------------------------------------------------------*/
  920. /*              Initialize the start session parameters               */
  921. /*--------------------------------------------------------------------*/
  922.  
  923.    memset( (void *) &sd, 0, sizeof sd );
  924.  
  925.    sd.Length      = 32;          /* Just basic info + InheritOpt     */
  926.  
  927.    sd.FgBg        = (USHORT) (foreground ? SSF_FGBG_FORE : SSF_FGBG_BACK);
  928.    sd.TraceOpt    = SSF_TRACEOPT_NONE;
  929.    sd.PgmName     = (PSZ) command;
  930.    sd.PgmInputs   = (PSZ) parameters;
  931.    sd.Environment = 0;           /* Just use our own envionment      */
  932.    sd.InheritOpt  = SSF_INHERTOPT_PARENT; /* Pass it to child        */
  933.    sd.SessionType = SSF_TYPE_DEFAULT;     /* Let the system pick
  934.                                              session type            */
  935.    sd.PgmControl  = (USHORT) (foreground ?
  936.                         SSF_CONTROL_MAXIMIZE : SSF_CONTROL_MINIMIZE);
  937.  
  938. /*--------------------------------------------------------------------*/
  939. /*          Build the queue to listen for the subtask ending          */
  940. /*--------------------------------------------------------------------*/
  941.  
  942.    if ( synchronous )
  943.    {
  944.       sprintf(queueName,
  945.               "\\queues\\pid%d\\pgm%d",
  946.               (int) getpid(),
  947.               instance++);
  948.  
  949.       rc = DosCreateQueue( &queueHandle,
  950. #ifdef __OS2__
  951.                            QUE_FIFO | QUE_CONVERT_ADDRESS,
  952. #else
  953.                            QUE_FIFO,
  954. #endif
  955.                            (PSZ) queueName );
  956.  
  957.       if ( rc )
  958.       {
  959.          printOS2error( queueName, rc );
  960.          return -4;                 /* Report command never was run     */
  961.       }
  962.  
  963.       sd.TermQ       = (PSZ) queueName;
  964.       sd.Related     = SSF_RELATED_CHILD;       /* Child session        */
  965.  
  966.    } /* if ( synchronous ) */
  967.    else {
  968.  
  969.       sd.TermQ       = (PSZ) 0;     /* Don't wait for session end       */
  970.       sd.Related     = SSF_RELATED_INDEPENDENT; /* Not a child session  */
  971.  
  972.    } /* else */
  973.  
  974.    rc = DosStartSession( &sd,
  975.                          &sessID,
  976.                          &childPID );
  977.  
  978.    if ( rc )
  979.    {
  980.       printOS2error( command ? command : parameters, rc );
  981.       return -5;
  982.    }
  983.  
  984. /*--------------------------------------------------------------------*/
  985. /*      If the command is running asynchonously return to caller      */
  986. /*--------------------------------------------------------------------*/
  987.  
  988.    if ( ! synchronous )
  989.       return 0;
  990.  
  991. /*--------------------------------------------------------------------*/
  992. /*                   Wait for the child to complete                   */
  993. /*--------------------------------------------------------------------*/
  994.  
  995.    memset( (void *) &queueRequest, 0, sizeof queueRequest );
  996.  
  997.    rc = DosReadQueue( queueHandle,
  998.                       &queueRequest,
  999.                       &queueDataLength,
  1000.                       &queueDataAddress,
  1001.                       0,            /* First element in the queue    */
  1002.                       0,            /* Wait for queue to be ready    */
  1003.                       &queueElementPriority,
  1004.                       0);           /* Semaphore handle -- not used  */
  1005.  
  1006.    if ( rc )
  1007.    {
  1008.       printOS2error( queueName, rc );
  1009.       panic();
  1010.    }
  1011.  
  1012.    rc = ((unsigned short FAR*) queueDataAddress)[1];
  1013.  
  1014. #ifdef __OS2__
  1015.    DosFreeMem( queueDataAddress );
  1016. #else
  1017.    DosFreeSeg( SELECTOROF(queueDataAddress) );
  1018. #endif
  1019.  
  1020.    return rc;
  1021.  
  1022. } /* executeAsync */
  1023.  
  1024. #endif
  1025.