Diff for /parser3/src/main/pa_exec.C between versions 1.48.2.18.2.1 and 1.52

version 1.48.2.18.2.1, 2003/03/18 15:14:18 version 1.52, 2003/09/25 09:15:03
Line 33  static DWORD CreateHiddenConsoleProcess( Line 33  static DWORD CreateHiddenConsoleProcess(
                                         LPHANDLE phOutRead,                                          LPHANDLE phOutRead,
                                         LPHANDLE phErrRead)                                          LPHANDLE phErrRead)
 {  {
     DWORD result=0;          DWORD result=0;
         BOOL fCreated;          BOOL fCreated;
     STARTUPINFO si;          STARTUPINFO si;
     SECURITY_ATTRIBUTES sa={0};          SECURITY_ATTRIBUTES sa={0};
     HANDLE hInRead;          HANDLE hInRead;
     HANDLE hOutWrite;          HANDLE hOutWrite;
     HANDLE hErrWrite;          HANDLE hErrWrite;
           
     // Create pipes          // Create pipes
     // initialize security attributes for handle inheritance (for WinNT)          // initialize security attributes for handle inheritance (for WinNT)
     sa.nLength=sizeof(sa);          sa.nLength=sizeof(sa);
     sa.bInheritHandle=TRUE;          sa.bInheritHandle=TRUE;
     sa.lpSecurityDescriptor=NULL;          sa.lpSecurityDescriptor=NULL;
           
     // create STDIN pipe          // create STDIN pipe
     if(!CreatePipe(&hInRead, phInWrite, &sa, 0))          if(!CreatePipe(&hInRead, phInWrite, &sa, 0))
         goto error;                  goto error;
           
     // create STDOUT pipe          // create STDOUT pipe
     if(!CreatePipe(phOutRead, &hOutWrite, &sa, 0))          if(!CreatePipe(phOutRead, &hOutWrite, &sa, 0))
         goto error;                  goto error;
           
     // create STDERR pipe          // create STDERR pipe
     if(!CreatePipe(phErrRead, &hErrWrite, &sa, 0))          if(!CreatePipe(phErrRead, &hErrWrite, &sa, 0))
         goto error;                  goto error;
           
     // process startup information          // process startup information
     memset(&si, 0, sizeof(si));          memset(&si, 0, sizeof(si));
     si.cb=sizeof(si);           si.cb=sizeof(si); 
     si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;          si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
     // child process' console must be hidden for Win95 compatibility          // child process' console must be hidden for Win95 compatibility
     si.wShowWindow=SW_HIDE;          si.wShowWindow=SW_HIDE;
     // assign "other" sides of pipes          // assign "other" sides of pipes
     si.hStdInput=hInRead;          si.hStdInput=hInRead;
     si.hStdOutput=hOutWrite;          si.hStdOutput=hOutWrite;
     si.hStdError=hErrWrite;          si.hStdError=hErrWrite;
           
         // calculating script's directory          // calculating script's directory
         char dir[MAX_STRING];          char dir[MAX_STRING];
         strncpy(dir, szCmdLine, MAX_STRING-1); dir[MAX_STRING-1]=0;          strncpy(dir, szCmdLine, MAX_STRING-1); dir[MAX_STRING-1]=0;
         lsplit(dir,' '); // trim arguments          lsplit(dir,' '); // trim arguments
         rsplit(dir,'/'); rsplit(dir,'\\'); // trim filename          rsplit(dir,'/'); rsplit(dir,'\\'); // trim filename
         chdir(dir);          chdir(dir);
           
     // Create a child process (suspended)          // Create a child process (suspended)
     fCreated=CreateProcess(NULL,          fCreated=CreateProcess(NULL,
                               (LPTSTR)szCmdLine,                  (LPTSTR)szCmdLine,
                               NULL,                  NULL,
                               NULL,                  NULL,
                               TRUE,                  TRUE,
                               CREATE_NO_WINDOW,                  CREATE_NO_WINDOW,
                               szEnv,                  szEnv,
                               dir,                  dir,
                               &si,                  &si,
                               ppi);                  ppi);
         if(!fCreated)          if(!fCreated)
                 result=GetLastError();                  result=GetLastError();
           
     CloseHandle(hInRead);          CloseHandle(hInRead);
     CloseHandle(hOutWrite);          CloseHandle(hOutWrite);
     CloseHandle(hErrWrite);          CloseHandle(hErrWrite);
           
     if(!fCreated)          if(!fCreated)
         goto error;                  goto error;
           
     return result;          return result;
           
 error:  error:
         if(!result/*yet*/)          if(!result/*yet*/)
                 result=GetLastError(); // get it                  result=GetLastError(); // get it
           
     CloseHandle(*phInWrite);          CloseHandle(*phInWrite);
     CloseHandle(*phOutRead);          CloseHandle(*phOutRead);
     CloseHandle(*phErrRead);          CloseHandle(*phErrRead);
           
     return result;          return result;
 }  }
   
 static const String& read_pipeHANDLE hOutRead, const char* file_spec,   static void read_pipe(String& result, HANDLE hOutRead, String::Language lang){
                                           String::Untaint_lang lang){  
         const String& result(new String);  
         while(true) {          while(true) {
                 char *buf=new char[MAX_STRING];                  char *buf=new(PointerFreeGC) char[MAX_STRING];
                 unsigned long size;                  unsigned long size;
                 if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size)                   if(!ReadFile(hOutRead, buf, MAX_STRING-1, &size, NULL) || !size) 
                         break;                          break;
                 result->APPEND(buf, size, lang, file_spec, 0);                  buf[size]=0;
     }                  result.append_know_length(buf, size, lang);
         return result;          }
 }  }
   
 static const char* buildCommand(const char* file_spec_cstr, const ArrayString& argv) {  static const char* buildCommand(const char* file_spec_cstr, const ArrayString& argv) {
Line 137  static const char* buildCommand(const ch Line 135  static const char* buildCommand(const ch
                                 if(*begin==' ') // alx: were an old magic for some linux-es                                  if(*begin==' ') // alx: were an old magic for some linux-es
                                         begin++;                                          begin++;
                                 if(char *end=strchr(begin, '\n')) {                                  if(char *end=strchr(begin, '\n')) {
                                         String string(begin, end-begin);                                          String string(pa_strdup(begin, end-begin));
                                         string << " " << file_spec_cstr;                                          string << " " << file_spec_cstr;
                                         result=string.cstr();                                          result=string.cstr();
                                 }                                  }
Line 151  static const char* buildCommand(const ch Line 149  static const char* buildCommand(const ch
         }          }
         { // appending argv          { // appending argv
                 String string(result);                  String string(result);
                 for(int i=0; i<argv.count(); i++) {                  for(size_t i=0; i<argv.count(); i++) {
                         string << " ";                          string << " ";
                         string << *argv[i];                          string << *argv[i];
                 }                  }
Line 279  static int get_exit_status(int pid) { Line 277  static int get_exit_status(int pid) {
                 WEXITSTATUS(status) : -2;                  WEXITSTATUS(status) : -2;
 }  }
   
 static const String& read_pipeint file, const char* file_spec, String::Untaint_lang lang){  static void read_pipe(String& result, int file, String::Language lang){
         const String& result(new String);  
         while(true) {          while(true) {
                 char *buf=new char[MAX_STRING];                  char *buf=new(PointerFreeGC) char[MAX_STRING];
                 ssize_t size=read(file, buf, MAX_STRING);                  ssize_t length=read(file, buf, MAX_STRING-1);
                 if(size<=0)                  if(length<=0)
                         break;                          break;
                 result->APPEND(buf, size, lang, file_spec, 0);                  buf[length]=0;
     }                  result.append_know_length(buf, length, lang);
         return result;          }
 }  }
   
 #endif  #endif
Line 296  static const String& read_pipeint file, Line 293  static const String& read_pipeint file,
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct Append_env_pair_info {  struct Append_env_pair_info {
 #ifdef WIN32  #ifdef WIN32
         String* string;          String& string;
           Append_env_pair_info(String& astring): string(astring) {}
 #else  #else
         ;  
         char **env_ref;          char **env_ref;
 #endif  #endif
 };  };
 #endif  #endif
 ///@test maybe here and at argv construction --- cstr(String::UL_UNSPECIFIED  ///@test maybe here and at argv construction --- cstr(String::L_UNSPECIFIED
 static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value,  static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value,
                 Append_env_pair_info *info) {                  Append_env_pair_info *info) {
 #ifdef WIN32  #ifdef WIN32
         *info->string << key << "=" << value;          info->string << key << "=" << value;
         info->string->APPEND_AS_IS("", 1, 0, 0); // zero byte          info->string.append_know_length("\1", 1, String::L_AS_IS); // placeholder for of zero byte
 #else  #else
         String string;          String::Body body;
         string << key << "=" << value;          body << key << "=" << value;
   
         *(info->env_ref++)=string.cstr(*info->pool, String::UL_UNSPECIFIED);          *(info->env_ref++)=body.cstrm();
 #endif  #endif
 }  }
   
Line 329  PA_exec_result pa_exec( Line 326  PA_exec_result pa_exec(
 #ifdef NO_PA_EXECS  #ifdef NO_PA_EXECS
         if(!forced_allow)          if(!forced_allow)
                 throw Exception("parser.runtime",                  throw Exception("parser.runtime",
                         file_spec,                          &file_spec,
                         "parser execs are disabled [recompile parser without --disable-execs configure option]");                          "parser execs are disabled [recompile parser without --disable-execs configure option]");
 #endif  #endif
   
         char* file_spec_cstr=file_spec->cstr(pool, String::UL_FILE_SPEC);           // execve needs non const
           char* file_spec_cstr=file_spec.cstrm(String::L_FILE_SPEC); 
 #ifdef WIN32  #ifdef WIN32
   
         PROCESS_INFORMATION pi;           PROCESS_INFORMATION pi; 
         HANDLE hInWrite, hOutRead, hErrRead;          HANDLE hInWrite, hOutRead, hErrRead;
         const char* cmd=buildCommand(file_spec->cstr(String::UL_FILE_SPEC), argv);          const char* cmd=buildCommand(file_spec.cstr(String::L_FILE_SPEC), argv);
         const char* env_cstr;          char* env_cstr;
         if(env) {          if(env) {
                 String string;                  String string;
                 Append_env_pair_info info={&string};                  Append_env_pair_info info(string);
                 env->for_each(append_env_pair, &info);                  env->for_each(append_env_pair, &info);
                 env_cstr=info.string->cstr(String::UL_UNSPECIFIED);                  env_cstr=info.string.cstrm(String::L_UNSPECIFIED);
                   for(char* replacer=env_cstr; *replacer; replacer++)
                           if(*replacer=='\1')
                                   *replacer=0;
         }          }
         if(DWORD error=CreateHiddenConsoleProcess(cmd, env_cstr, &pi, &hInWrite, &hOutRead, &hErrRead)) {          if(DWORD error=CreateHiddenConsoleProcess(cmd, env_cstr, &pi, &hInWrite, &hOutRead, &hErrRead)) {
                 char szErrorDesc[MAX_STRING];                  char szErrorDesc[MAX_STRING];
                 const char *param="the file you tried to run";                  const char* param="the file you tried to run";
                 size_t error_size=FormatMessage(                  size_t error_size=FormatMessage(
                         FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ARGUMENT_ARRAY , NULL, error,                          FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ARGUMENT_ARRAY , NULL, error,
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
Line 357  PA_exec_result pa_exec( Line 358  PA_exec_result pa_exec(
                         szErrorDesc[error_size-3]=0;                          szErrorDesc[error_size-3]=0;
                           
                 throw Exception(0,                  throw Exception(0,
                         file_spec,                          &file_spec,
                         "exec failed - %s (%ld). Consider adding shbang line (#!x:\\interpreter\\command line)",                           "exec failed - %s (%ld). Consider adding shbang line (#!x:\\interpreter\\command line)", 
                                 error_size?szErrorDesc:"<unknown>", (long)error);                                  error_size?szErrorDesc:"<unknown>", (long)error);
         } else {          } else {
                 const char* in_cstr=in.cstr();                  const char* in_cstr=in.cstr();
                 DWORD written_size;                  DWORD written_size;
                 WriteFile(hInWrite, in_cstr, in.size(), &written_size, NULL);                  WriteFile(hInWrite, in_cstr, in.length(), &written_size, NULL);
                 // EOF for stupid text reads                  // EOF for stupid text reads
                 // normally they should read CONTENT_LENGTH bytes,                  // normally they should read CONTENT_LENGTH bytes,
                 // without this char                  // without this char
                 WriteFile(hInWrite, "\x1A", 1, &written_size, NULL);                  WriteFile(hInWrite, "\x1A", 1, &written_size, NULL);
                 CloseHandle(hInWrite);                  CloseHandle(hInWrite);
                 result.out=read_pipe(pool, hOutRead, file_spec_cstr, String::UL_AS_IS);                  read_pipe(result.out, hOutRead, String::L_AS_IS);
                 CloseHandle(hOutRead);                  CloseHandle(hOutRead);
                 result.err=read_pipe(pool, hErrRead, file_spec_cstr, String::UL_TAINTED);                                 read_pipe(result.err, hErrRead, String::L_TAINTED);             
                 CloseHandle(hErrRead);                  CloseHandle(hErrRead);
 /*        /*      
 from http://www.apache.org/websrc/cvsweb.cgi/apache-1.3/src/main/util_script.c?rev=1.151&content-type=text/vnd.viewcvs-markup  from http://www.apache.org/websrc/cvsweb.cgi/apache-1.3/src/main/util_script.c?rev=1.151&content-type=text/vnd.viewcvs-markup
Line 392  from http://www.apache.org/websrc/cvsweb Line 393  from http://www.apache.org/websrc/cvsweb
                 struct stat finfo;                  struct stat finfo;
                 if(stat(file_spec_cstr, &finfo)!=0)                  if(stat(file_spec_cstr, &finfo)!=0)
                         throw Exception("file.missing",                           throw Exception("file.missing", 
                                         file_spec,                                   &file_spec, 
                                         "stat failed: %s (%d), actual filename '%s'",                                   "stat failed: %s (%d), actual filename '%s'", 
                                                 strerror(errno), errno, file_spec_cstr);                                          strerror(errno), errno, file_spec_cstr);
   
                 if(finfo.st_uid/*foreign?*/!=geteuid()                  check_safe_mode(finfo, file_spec, file_spec_cstr);
                         && finfo.st_gid/*foreign?*/!=getegid())  
                         throw Exception("parser.runtime",   
                                 file_spec,   
                                 "parser is in safe mode: executing files of foreign group and user disabled [recompile parser with --disable-safe-mode configure option], actual filename '%s'",   
                                         file_spec_cstr);  
         }          }
 #endif  #endif
   
         char * argv_cstrs[1+10+1]={file_spec_cstr, 0};          char* argv_cstrs[1+10+1]={file_spec_cstr, 0};
         const int argv_size=argv.count();          const int argv_size=argv.count();
         const int argv_max=sizeof(argv_cstrs)/sizeof(argv_cstrs[0])-1-1;          const int argv_max=sizeof(argv_cstrs)/sizeof(argv_cstrs[0])-1-1;
         if(argv_size>argv_max)          if(argv_size>argv_max)
                 throw Exception("parser.runtime",                  throw Exception("parser.runtime",
                         file_spec,                          &file_spec,
                         "too many arguments (%d > max %d)", argv_size, argv_max);                          "too many arguments (%d > max %d)", argv_size, argv_max);
         for(int i=0; i<argv_size; i++)          for(int i=0; i<argv_size; i++)
                 argv_cstrs[1+i]=argv[i]->cstr();                  argv_cstrs[1+i]=argv[i]->cstrm();
         argv_cstrs[1+argv_size]=0;          argv_cstrs[1+argv_size]=0;
   
         char **env_cstrs;          char **env_cstrs;
         if(env) {          if(env) {
                 env_cstrs=new char *[env->count()+1/*0*/];                  env_cstrs=new(PointerFreeGC) char *[env->count()+1/*0*/];
                 Append_env_pair_info info={&pool, env_cstrs};                   Append_env_pair_info info={env_cstrs}; 
                 env->for_each(append_env_pair, &info);                  env->for_each(append_env_pair, &info);
                 *info.env_ref=0;                  *info.env_ref=0;
         } else          } else
Line 431  from http://www.apache.org/websrc/cvsweb Line 427  from http://www.apache.org/websrc/cvsweb
                 &pipe_write, &pipe_read, &pipe_err);                  &pipe_write, &pipe_read, &pipe_err);
         if(pid>0) {          if(pid>0) {
                 // in child                  // in child
                 if(in.size()) {// there is some in data                  if(in.length()) {// there is some in data
                         const char* in_cstr=in.cstr();                          const char* in_cstr=in.cstr();
                         write(pipe_write, in_cstr, in.size());                          write(pipe_write, in_cstr, in.length());
                 }                  }
                 close(pipe_write);                  close(pipe_write);
                 result.out=read_pipe(pool, pipe_read, file_spec_cstr, String::UL_AS_IS);                  read_pipe(result.out, pipe_read, String::L_AS_IS);
                 close(pipe_read);                  close(pipe_read);
                 result.err=read_pipe(pool, pipe_err, file_spec_cstr, String::UL_TAINTED);                  read_pipe(result.err, pipe_err, String::L_TAINTED);
                 close(pipe_err);                  close(pipe_err);
   
                 result.status=get_exit_status(pid); // negative may mean "-errno[execl()]"                  result.status=get_exit_status(pid); // negative may mean "-errno[execl()]"
         } else           } else 
                 throw Exception(0,                  throw Exception(0,
                         file_spec,                          &file_spec,
                         "%s error: %s (%d)", pid<0?"fork":"pipe", strerror(errno), errno);                           "%s error: %s (%d)", pid<0?"fork":"pipe", strerror(errno), errno); 
 #endif  #endif
   

Removed from v.1.48.2.18.2.1  
changed lines
  Added in v.1.52


E-mail: