--- parser3/src/main/pa_exec.C 2002/04/16 09:38:49 1.35 +++ parser3/src/main/pa_exec.C 2003/04/04 14:42:38 1.49 @@ -1,15 +1,16 @@ /** @file Parser: program executing for different OS-es. - Copyright(c) 2000,2001, 2002 ArtLebedev Group(http://www.artlebedev.com) + Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - $Id: pa_exec.C,v 1.35 2002/04/16 09:38:49 paf Exp $ - + portions by Victor Fedoseev" [January 23, 2003] @todo setrlimit */ +static const char* IDENT_EXEC_C="$Date: 2003/04/04 14:42:38 $"; + #include "pa_config_includes.h" #include "pa_exec.h" @@ -27,14 +28,15 @@ #ifdef WIN32 /// this func from http://www.ccas.ru/~posp/popov/spawn.htm -static BOOL WINAPI CreateHiddenConsoleProcess(LPCTSTR szCmdLine, - char *szEnv, +static DWORD CreateHiddenConsoleProcess(LPCTSTR szCmdLine, + char *szEnv, PROCESS_INFORMATION* ppi, LPHANDLE phInWrite, LPHANDLE phOutRead, LPHANDLE phErrRead) { - BOOL fCreated; + DWORD result=0; + BOOL fCreated; STARTUPINFO si; SECURITY_ATTRIBUTES sa={0}; HANDLE hInRead; @@ -88,6 +90,8 @@ static BOOL WINAPI CreateHiddenConsolePr dir, &si, ppi); + if(!fCreated) + result=GetLastError(); CloseHandle(hInRead); CloseHandle(hOutWrite); @@ -96,28 +100,19 @@ static BOOL WINAPI CreateHiddenConsolePr if(!fCreated) goto error; - return TRUE; + return result; error: + if(!result/*yet*/) + result=GetLastError(); // get it + CloseHandle(*phInWrite); CloseHandle(*phOutRead); CloseHandle(*phErrRead); - return FALSE; -} - -static void read_pipe(String& result, HANDLE hOutRead, const char *file_spec, - String::Untaint_lang lang){ - while(true) { - char *buf=(char *)result.pool().malloc(MAX_STRING); - unsigned long size; - if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size) - break; - result.APPEND(buf, size, lang, file_spec, 0); - } + return result; } - static const char *buildCommand(Pool& pool, const String& origin_string, const char *file_spec_cstr, const Array *argv) { @@ -136,9 +131,6 @@ static const char *buildCommand(Pool& po string.APPEND_AS_IS(begin, end-begin, origin_string.origin().file, 0); string << " " << file_spec_cstr; - if(argv) - for(int i=0; isize(); i++) - string << argv->get_string(i)->cstr(); result=string.cstr(); } } @@ -159,12 +151,12 @@ static const char *buildCommand(Pool& po return result; } -#else +#else // WIN32 -static int execve_piped(const char *file_spec_cstr, +static pid_t execve_piped(const char *file_spec_cstr, char * const argv[], char * const env[], int *pipe_in, int *pipe_out, int *pipe_err) { - int pid; + pid_t pid; int in_fds[2]; int out_fds[2]; int err_fds[2]; @@ -209,7 +201,7 @@ static int execve_piped(const char *file close(err_fds[0]); close(err_fds[1]); } errno=save_errno; - return 0; + return -1; } if(!pid) { @@ -233,7 +225,8 @@ static int execve_piped(const char *file close(err_fds[1]); } - /* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */ + /* grabbed this from Apache source: */ + /* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */ signal(SIGCHLD, SIG_DFL); /* Was that it? */ // chdir to script's directory @@ -275,17 +268,79 @@ static int get_exit_status(int pid) { WEXITSTATUS(status) : -2; } -static void read_pipe(String& result, int file, const char *file_spec, String::Untaint_lang lang){ +#endif // WIN32 + +static void read_pipe(String& result, +#ifdef WIN32 + HANDLE hOutRead, +#else // WIN32 + int file, +#endif // WIN32 + const char *file_spec, + String::Untaint_lang lang, + int *header_pos=0, const char **eol_marker=0, size_t *eol_marker_size=0){ + + if(header_pos) *header_pos = -1; + if(eol_marker) *eol_marker = ""; + if(eol_marker_size) *eol_marker_size = 0; + + int dos_seq_match = 0; + int unix_seq_match = 0; + int blk_pos = 0; + bool do_search = (header_pos || eol_marker || eol_marker_size); + while(true) { char *buf=(char *)result.pool().malloc(MAX_STRING); - size_t size=read(file, buf, MAX_STRING); - if(!size) +#ifdef WIN32 + unsigned long size, i; + if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size) + break; +#else // WIN32 + ssize_t i, size=read(file, buf, MAX_STRING); + if(size<=0) break; +#endif // WIN32 + if(do_search){ + for(i=0; i3) // ".\r\n" + szErrorDesc[error_size-3]=0; + + throw Exception(0, + &file_spec, + "exec failed - %s (%ld). Consider adding shbang line (#!x:\\interpreter\\command line)", + error_size?szErrorDesc:"", (long)error); + } else { const char *in_cstr=in.cstr(); DWORD written_size; WriteFile(hInWrite, in_cstr, in.size(), &written_size, NULL); @@ -339,7 +409,7 @@ int pa_exec( // without this char WriteFile(hInWrite, "\x1A", 1, &written_size, NULL); CloseHandle(hInWrite); - read_pipe(out, hOutRead, file_spec_cstr, String::UL_AS_IS); + read_pipe(out, hOutRead, file_spec_cstr, String::UL_AS_IS, header_pos, eol_marker, eol_marker_size); CloseHandle(hOutRead); read_pipe(err, hErrRead, file_spec_cstr, String::UL_TAINTED); CloseHandle(hErrRead); @@ -351,21 +421,6 @@ from http://www.apache.org/websrc/cvsweb */ CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - } else { - DWORD error=GetLastError(); - char szErrorDesc[MAX_STRING]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), - szErrorDesc, sizeof(szErrorDesc), NULL); - size_t error_size=strlen(szErrorDesc); - if(error_size>3) // ".\r\n" - szErrorDesc[error_size-3]=0; - - throw Exception(0, - &file_spec, - "(real command line=\"%s\") exec failed - %s (%ld)", - cmd, - szErrorDesc, (long)error); } #else @@ -373,7 +428,7 @@ from http://www.apache.org/websrc/cvsweb int pipe_write, pipe_read, pipe_err; char *file_spec_cstr=file_spec.cstr(String::UL_FILE_SPEC); -#ifdef NO_FOREIGN_GROUP_FILES +#ifdef PA_SAFE_MODE if(!forced_allow) { struct stat finfo; if(stat(file_spec_cstr, &finfo)!=0) @@ -382,10 +437,11 @@ from http://www.apache.org/websrc/cvsweb "stat failed: %s (%d), actual filename '%s'", strerror(errno), errno, file_spec_cstr); - if(finfo.st_gid/*foreign?*/!=getegid()) - throw Exception("parser.runtime", - &file_spec, - "parser executing files of foreign group is disabled [recompile parser without --disable-foreign-group-files configure option], actual filename '%s'", + if(finfo.st_uid/*foreign?*/!=geteuid() + && 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 @@ -411,16 +467,17 @@ from http://www.apache.org/websrc/cvsweb *env_ref=0; } - int pid=execve_piped( + pid_t pid=execve_piped( file_spec_cstr, argv_cstrs, env_cstrs, &pipe_write, &pipe_read, &pipe_err); - if(pid) { + if(pid>0) { // in child const char *in_cstr=in.cstr(); - write(pipe_write, in_cstr, in.size()); + if(*in_cstr) // there is some in data + write(pipe_write, in_cstr, in.size()); close(pipe_write); - read_pipe(out, pipe_read, file_spec_cstr, String::UL_AS_IS); + read_pipe(out, pipe_read, file_spec_cstr, String::UL_AS_IS, header_pos, eol_marker, eol_marker_size); close(pipe_read); read_pipe(err, pipe_err, file_spec_cstr, String::UL_TAINTED); close(pipe_err); @@ -429,7 +486,7 @@ from http://www.apache.org/websrc/cvsweb } else throw Exception(0, &file_spec, - "pipe error"); + "%s error: %s (%d)", pid<0?"fork":"pipe", strerror(errno), errno); #endif return 0;