Diff for /parser3/src/main/pa_exec.C between versions 1.48.2.3 and 1.48.2.18.2.4

version 1.48.2.3, 2003/01/29 12:02:23 version 1.48.2.18.2.4, 2003/03/20 14:19:09
Line 1 Line 1
 /** @file  /** @file
         Parser: program executing for different OS-es.          Parser: program executing for different OS-es.
   
         Copyright(c) 2000,2001, 2003 ArtLebedev Group(http://www.artlebedev.com)          Copyright(c) 2000,2001-2003 ArtLebedev Group(http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
   
         @todo setrlimit          @todo setrlimit
Line 14  static const char* IDENT_EXEC_C="$Date$" Line 14  static const char* IDENT_EXEC_C="$Date$"
 #include "pa_exec.h"  #include "pa_exec.h"
 #include "pa_exception.h"  #include "pa_exception.h"
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_value_includes.h"  
   
 #ifdef WIN32  #ifdef WIN32
 #       include <windows.h>  #       include <windows.h>
Line 112  error: Line 111  error:
     return result;      return result;
 }  }
   
 static void read_pipe(Pool& pool, StringPtr result, HANDLE hOutRead, const char *file_spec,   static const String& read_pipeHANDLE hOutRead, const char* file_spec, 
                                           String::Untaint_lang lang){                                            String::Untaint_lang lang){
           const String& result(new String);
         while(true) {          while(true) {
                 char *buf=new(pool) char[MAX_STRING];                  char *buf=new char[MAX_STRING];
                 unsigned long size;                  unsigned long size;
                 if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size)                   if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size) 
                         break;                          break;
                 result->APPEND(buf, size, lang, file_spec, 0);                  result->APPEND(buf, size, lang, file_spec, 0);
     }      }
           return result;
 }  }
   
 static CharPtr buildCommand(CharPtr file_spec_cstr, const Array<ConstStringPtr>& argv) {  static const char* buildCommand(const char* file_spec_cstr, const ArrayString& argv) {
         CharPtr result=file_spec_cstr;          const char* result=file_spec_cstr;
         if(FILE *f=fopen(file_spec_cstr, "r")) {          if(FILE *f=fopen(file_spec_cstr, "r")) {
                 try {                  try {
                 char buf[MAX_STRING];                  char buf[MAX_STRING];
Line 132  static CharPtr buildCommand(CharPtr file Line 133  static CharPtr buildCommand(CharPtr file
                 if(size>2) {                  if(size>2) {
                         buf[size]=0;                          buf[size]=0;
                         if(strncmp(buf, "#!", 2)==0) {                          if(strncmp(buf, "#!", 2)==0) {
                                 const char *begin=buf+2;                                  const char* begin=buf+2;
                                 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')) {
Line 163  static CharPtr buildCommand(CharPtr file Line 164  static CharPtr buildCommand(CharPtr file
   
 #else  #else
   
 static pid_t execve_piped(const char *file_spec_cstr,   static pid_t execve_piped(const char* file_spec_cstr, 
                         char * const argv[], char * const env[],                          char * const argv[], char * const env[],
                         int *pipe_in, int *pipe_out, int *pipe_err) {                          int *pipe_in, int *pipe_out, int *pipe_err) {
         pid_t pid;          pid_t pid;
Line 278  static int get_exit_status(int pid) { Line 279  static int get_exit_status(int pid) {
                 WEXITSTATUS(status) : -2;                  WEXITSTATUS(status) : -2;
 }  }
   
 static void read_pipe(String& result, int file, const char *file_spec, String::Untaint_lang lang){  static const String& read_pipeint file, const char* file_spec, String::Untaint_lang lang){
           const String& result(new String);
         while(true) {          while(true) {
                 char *buf=(char *)result.pool().malloc(MAX_STRING);                  char *buf=new char[MAX_STRING];
                 ssize_t size=read(file, buf, MAX_STRING);                  ssize_t size=read(file, buf, MAX_STRING);
                 if(size<=0)                  if(size<=0)
                         break;                          break;
                 result.APPEND(buf, size, lang, file_spec, 0);                  result->APPEND(buf, size, lang, file_spec, 0);
     }      }
           return result;
 }  }
   
 #endif  #endif
   
 ///@test maybe here and at argv construction --- cstr(String::UL_UNSPECIFIED  #ifndef DOXYGEN
 static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value,   struct Append_env_pair_info {
 #ifdef WIN32  #ifdef WIN32
                                                                 String *string          String* string;
 #else  #else
                                                                 struct {          ;
                                                                         Pool *pool;          char **env_ref;
                                                                         char ***env  
                                                                 } info  
 #endif  #endif
                                                         ) {  };
   #endif
   ///@test maybe here and at argv construction --- cstr(String::UL_UNSPECIFIED
   static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value,
                   Append_env_pair_info *info) {
 #ifdef WIN32  #ifdef WIN32
         *string << key << "=" << value;          *info->string << key << "=" << value;
         string->APPEND_AS_IS("", 1, 0, 0); // zero byte          info->string->APPEND_AS_IS("", 1, 0, 0); // zero byte
 #else  #else
         String string;          String string;
         string << key << "=" << value;          string << key << "=" << value;
   
         **env=string.cstr(*info->pool, String::UL_UNSPECIFIED);  (*env)++;          *(info->env_ref++)=string.cstr(*info->String::UL_UNSPECIFIED);
 #endif  #endif
 }  }
   
 /// @todonow unix part to smart_ptr  /// @todonow unix part to smart_ptr
 int pa_exec(Pool& pool,  PA_exec_result pa_exec(
                         bool forced_allow,                           bool forced_allow, 
                         ConstStringPtr file_spec,                           const String& file_spec, 
                         HashStringString& env,                           const HashStringString* env, 
                         Array<ConstStringPtr>& argv,                           const ArrayString& argv, 
                         ConstStringPtr in, StringPtr out, StringPtr err) {                          String& in) {
           PA_exec_result result;
   
 #ifdef NO_PA_EXECS  #ifdef NO_PA_EXECS
         if(!forced_allow)          if(!forced_allow)
                 throw Exception("parser.runtime",                  throw Exception("parser.runtime",
Line 326  int pa_exec(Pool& pool, Line 333  int pa_exec(Pool& pool,
                         "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(String::UL_FILE_SPEC); 
 #ifdef WIN32  #ifdef WIN32
   
         PROCESS_INFORMATION pi;           PROCESS_INFORMATION pi; 
         HANDLE hInWrite, hOutRead, hErrRead;          HANDLE hInWrite, hOutRead, hErrRead;
         CharPtr file_spec_cstr=file_spec->cstr(String::UL_FILE_SPEC);           const char* cmd=buildCommand(file_spec->cstr(String::UL_FILE_SPEC), argv);
         CharPtr cmd=buildCommand(file_spec_cstr, argv);          const char* env_cstr;
         CharPtr env_cstr(0);          if(env) {
         { // env  
                 String string;                  String string;
                 env.for_each(append_env_pair, &string);                  Append_env_pair_info info={&string};
                 env_cstr=string.cstr(String::UL_UNSPECIFIED);                  env->for_each(append_env_pair, &info);
                   env_cstr=info.string->cstr(String::UL_UNSPECIFIED);
         }          }
         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];
                 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),
                         szErrorDesc, sizeof(szErrorDesc), &param);                          szErrorDesc, sizeof(szErrorDesc), (va_list *)&param);
                 if(error_size>3) // ".\r\n"                  if(error_size>3) // ".\r\n"
                         szErrorDesc[error_size-3]=0;                          szErrorDesc[error_size-3]=0;
                           
Line 353  int pa_exec(Pool& pool, Line 361  int pa_exec(Pool& pool,
                         "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 {
                 CharPtr 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);
                 read_pipe(pool, out, hOutRead, file_spec_cstr, String::UL_AS_IS);                  result.out=read_pipe(hOutRead, file_spec_cstr, String::UL_AS_IS);
                 CloseHandle(hOutRead);                  CloseHandle(hOutRead);
                 read_pipe(pool, err, hErrRead, file_spec_cstr, String::UL_TAINTED);                               result.err=read_pipe(hErrRead, file_spec_cstr, String::UL_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 378  from http://www.apache.org/websrc/cvsweb Line 386  from http://www.apache.org/websrc/cvsweb
 #else  #else
   
         int pipe_write, pipe_read, pipe_err;          int pipe_write, pipe_read, pipe_err;
         char *file_spec_cstr=file_spec.cstr(String::UL_FILE_SPEC);  
   
 #ifdef PA_SAFE_MODE  #ifdef PA_SAFE_MODE
         if(!forced_allow) {          if(!forced_allow) {
                 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()                  if(finfo.st_uid/*foreign?*/!=geteuid()
                         && finfo.st_gid/*foreign?*/!=getegid())                          && finfo.st_gid/*foreign?*/!=getegid())
                         throw Exception("parser.runtime",                           throw Exception("parser.runtime", 
                                 &file_spec,                                   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'",                                   "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);                                          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};
         if(argv) {          const int argv_size=argv.count();
                 const int argv_size=argv->size();          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->get_string(i)->cstr();          argv_cstrs[1+argv_size]=0;
                 argv_cstrs[1+argv_size]=0;  
         }          char **env_cstrs;
         char **env_cstrs=0;  
         if(env) {          if(env) {
                 env_cstrs=                  env_cstrs=new char *[env->count()+1/*0*/];
                         (char **)env->pool().malloc(sizeof(char *)*(env->size()+1/*0*/));                  Append_env_pair_info info={&env_cstrs}; 
                 char **env_ref=env_cstrs;                  env->for_each(append_env_pair, &info);
                 env->for_each(append_env_pair, &env_ref);                  *info.env_ref=0;
                 *env_ref=0;          } else
         }                  env_cstrs=0;
   
         pid_t pid=execve_piped(          pid_t pid=execve_piped(
                 file_spec_cstr,                  file_spec_cstr,
Line 425  from http://www.apache.org/websrc/cvsweb Line 431  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
                 const char *in_cstr=in.cstr();                  if(in.length()) {// there is some in data
                 if(*in_cstr) // there is some in data                          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);
                 read_pipe(out, pipe_read, file_spec_cstr, String::UL_AS_IS);                  result.out=read_pipe(pipe_read, file_spec_cstr, String::UL_AS_IS);
                 close(pipe_read);                  close(pipe_read);
                 read_pipe(err, pipe_err, file_spec_cstr, String::UL_TAINTED);                  result.err=read_pipe(pipe_err, file_spec_cstr, String::UL_TAINTED);
                 close(pipe_err);                  close(pipe_err);
   
                 return 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
   
         return 0;          return result;
 }  }

Removed from v.1.48.2.3  
changed lines
  Added in v.1.48.2.18.2.4


E-mail: