Changeset 1817 for trunk/gsdl/lib


Ignore:
Timestamp:
2000-12-20T11:30:34+13:00 (23 years ago)
Author:
sjboddie
Message:

Completely overhauled the way system calls are made on windows (i.e.
the gsdl_system() function), in the process removing the old gsdl_call_perl
function. Greenstone can now spawn console applications without the
annoying popup window so the collector is a little smoother and prettier.
Unfortunately, the old problem with the web library/apache server not
updating the browser page before a spawned process completes has again
reared its head. This seems the lesser of two evils though as the local
library is (hopefully) the version that the large majority of windows
users will use. I'll have another go at fixing the web library when I have
a chance.

Location:
trunk/gsdl/lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/gsdl/lib/gsdltools.cpp

    r1793 r1817  
    5353}
    5454
    55 // gsdl_system spawns a completely separate program (i.e. the calling
    56 // program continues and terminates normally). Arguments containing special
    57 // characters (e.g. '&') should be quoted with ""
     55// gsdl_system creates a new process for the cmd command (which
     56// may contain arguments).
     57// cmd should contain the full path of the program to run.
     58// The child process inherits the environment of the calling
     59// process.
     60// If sync is true a synchronous call will be made, otherwise
     61// an asyncronous call.
     62// If sync is true the return value will be the exit code of
     63// the child process or -1 if the child process wasn't started.
     64// If sync is false the return value will be 0 if the process
     65// was started ok or -1 if it failed.
     66int gsdl_system (const text_t &cmd, bool sync, ostream &logout) {
     67  if (cmd.empty()) return -1;
     68  char *cmd_c = cmd.getcstr();
    5869
    5970#if defined (__WIN32__)
    60 void gsdl_system (char *cmd, ostream &logout) {
    61 
     71  // the windows version - this is implemented this way
     72  // to prevent windows popping up all over the place when
     73  // we call a console application (like perl)
    6274  STARTUPINFO ps = {sizeof(STARTUPINFO), NULL, NULL, NULL,
    6375                    0, 0, 0, 0, 0, 0,
    64                     0, 0,
    65                     0, 0, NULL,
     76                    0, STARTF_USESHOWWINDOW,
     77                    SW_HIDE, 0, NULL,
    6678                    NULL, NULL, NULL};
    6779  PROCESS_INFORMATION pi;
    6880  BOOL res = CreateProcess(NULL,
    69                            cmd,
     81                           cmd_c,
    7082                           NULL,
    7183                           NULL,
    7284                           FALSE,
    73                            DETACHED_PROCESS,
     85               NULL,
    7486                           NULL,
    7587                           NULL,
     
    7789                           &pi);
    7890  if (!res) {
    79     logout << "Failed to start " << cmd << " process, error code " << GetLastError();
     91    logout << "gsdl_system failed to start " << cmd_c
     92       << " process, error code " << GetLastError();
     93    delete cmd_c;
     94    return -1;
    8095  }
     96
     97  DWORD ret = 0;
     98  if (sync) { // synchronous system call
     99    // wait until child process exits.
     100    WaitForSingleObject(pi.hProcess, INFINITE);
     101    // set ret to exit code of child process
     102    GetExitCodeProcess(pi.hProcess, &ret);
     103  }
    81104
    82105  CloseHandle(pi.hProcess);
    83106  CloseHandle(pi.hThread);
    84 }
    85107
    86108#else
    87 void gsdl_system (char *cmd, ostream &logout) {
     109  // the unix version
     110  int ret = 0;
     111  if (sync) { // synchronous system call
     112    // make sure the command interpreter is found
     113    if (system (NULL) == 0) {
     114      logout << "gsdl_system failed to start " << cmd_c
     115         << " process, command interpreter not found\n";
     116      delete cmd_c;
     117      return -1;
     118    }
     119    ret = system (cmd_c);
    88120
    89   if (cmd == NULL) return;
    90   int pid = fork();
    91   if (pid == -1) return;
    92   if (pid == 0) {
    93     // child process
    94     char *argv[4];
    95     argv[0] = "sh";
    96     argv[1] = "-c";
    97     argv[2] = cmd;
    98     argv[3] = 0;
    99     execv("/bin/sh", argv);
    100     //    exit(127);
     121  } else { // asynchronous system call
     122    int pid = fork();
     123    if (pid == -1) {
     124      delete cmd_c;
     125      return -1;
     126    }
     127    if (pid == 0) {
     128      // child process
     129      char *argv[4];
     130      argv[0] = "sh";
     131      argv[1] = "-c";
     132      argv[2] = cmd;
     133      argv[3] = 0;
     134      execv("/bin/sh", argv);
     135    }
    101136  }
    102 }
    103137#endif
    104138
    105 
    106 // gsdl_call_perl executes the perl script perl_cmd, passing it all the
    107 // arguments provided.
    108 
    109 // Arguments should be char*'s, the last argument should be NULL
    110 
    111 // perl_cmd shouldn't contain the path to the script as we use "perl -S"
    112 // to find it. This means that the PATH environment variable of the calling
    113 // process should contain the directory where the perl_cmd script lives.
    114 
    115 // Uses a standard system() call on unix and a synchronous _spawn() on windows.
    116 // We use the _spawn() because windows 9* doesn't seem to pass the
    117 // environment of the calling process to the new process when using
    118 // system (which we need to do).
    119 
    120 // all arguments will be quoted with double quotes [""] so they should be unquoted
    121 // when passed in.
    122 
    123 // returns the exit status of the called process (-1 if system() or _spawn() failed)
    124 
    125 int gsdl_call_perl (char *perl_cmd, ...) {
    126 
    127   va_list argn;
    128   char *thisarg = perl_cmd;
    129 
    130 #if defined(__WIN32__) && !defined (__GNUC__)
    131   int i = 2;
    132 #define GSDL_MAX_ARGS 20
    133   char *args[GSDL_MAX_ARGS];
    134   args[0] = "perl";
    135   args[1] = "-S";
    136 #else
    137   text_t cmd = "perl -S";
    138 #endif
    139 
    140   // get arguments
    141   va_start(argn, perl_cmd);
    142   while(thisarg != NULL) {
    143 #if defined(__WIN32__) && !defined (__GNUC__)
    144     if (i >= GSDL_MAX_ARGS) break;
    145     text_t tmp = thisarg;
    146     tmp = "\"" + tmp + "\"";
    147     args[i] = tmp.getcstr();
    148     i++;
    149 #else
    150     cmd += " \"";
    151     cmd += thisarg;
    152     cmd.push_back ('"');
    153 #endif
    154     thisarg = va_arg(argn, char *);
    155   }
    156   va_end(argn);
    157 
    158 #if defined(__WIN32__) && !defined (__GNUC__)
    159   args[i] = NULL;
    160   int rv = _spawnvp (_P_WAIT, "perl", args);
    161   while (--i > 2) delete (args[i]);
    162 #else
    163   char *cmdc = cmd.getcstr();
    164   int rv = system (cmdc);
    165   delete (cmdc);
    166 #endif
    167   return rv;
     139  delete cmd_c;
     140  return ret;
    168141}
    169142
    170143// attempts to work out if perl is functional
    171 bool perl_ok () {
     144bool perl_ok (ostream &logout) {
    172145#if defined(__WIN32__)
    173   int i = gsdl_call_perl ("-e", "exit 1", NULL);
     146  text_t cmd = "perl -e \"exit 1\"";
     147#else
     148  text_t cmd = "perl -e \"'exit 1'\"";
     149#endif;
     150  int i = gsdl_system (cmd, true, logout);
    174151  return (i == 1);
    175 #else
    176   int i = gsdl_call_perl ("-e", "'exit 0'", NULL); 
    177   return (i == 0);
    178 #endif
    179152}
  • trunk/gsdl/lib/gsdltools.h

    r1783 r1817  
    3636bool littleEndian();
    3737
    38 
    3938// escapes '\' and '_' characters with '\'
    4039// note that single '\' characters occurring
     
    4342text_t dm_safe (const text_t &instring);
    4443
     44// gsdl_system creates a new process for the cmd command (which
     45// may contain arguments).
     46// cmd should contain the full path of the program to run.
     47// The child process inherits the environment of the calling
     48// process.
     49// If sync is true a synchronous call will be made, otherwise
     50// an asyncronous call.
     51// If sync is true the return value will be the exit code of
     52// the child process or -1 if the child process wasn't started.
     53// If sync is false the return value will be 0 if the process
     54// was started ok or -1 if it failed.
     55int gsdl_system (const text_t &cmd, bool sync, ostream &logout);
    4556
    46 // gsdl_system spawns a completely separate program (i.e. the calling
    47 // program continues and terminates normally). Arguments containing special
    48 // characters (e.g. '&') should be quoted with ""
    49 void gsdl_system (char *cmd, ostream &logout);
     57// attempts to work out if perl is functional
     58bool perl_ok (ostream &logout);
     59
     60#endif
    5061
    5162
    52 // gsdl_call_perl executes the perl script perl_cmd, passing it all the
    53 // arguments provided.
    5463
    55 // Arguments should be text_t's, the last argument should be an empty text_t.
    5664
    57 // perl_cmd shouldn't contain the path to the script as we use "perl -S"
    58 // to find it. This means that the PATH environment variable of the calling
    59 // process should contain the directory where the perl_cmd script lives.
    6065
    61 // Uses a standard system() call on unix and a synchronous _spawn() on windows.
    62 // We use the _spawn() because windows 9* doesn't seem to pass the
    63 // environment of the calling process to the new process when using
    64 // system (which we need to do).
    6566
    66 // all arguments will be quoted with double quotes [""] so they should be unquoted
    67 // when passed in.
    6867
    69 // returns the exit status of the called process (-1 if system() or _spawn() failed)
    70 int gsdl_call_perl (char *perl_cmd, ...);
    71 
    72 // attempts to work out if perl is functional
    73 bool perl_ok ();
    74 
    75 #endif
Note: See TracChangeset for help on using the changeset viewer.