static HRESULT process_hook_section(install_ctx_t *ctx, const WCHAR *sect_name) { WCHAR buf[2048], val[2*MAX_PATH]; const WCHAR *key; DWORD len; HRESULT hres; static const WCHAR runW[] = {'r','u','n',0}; len = GetPrivateProfileStringW(sect_name, NULL, NULL, buf, sizeof(buf)/sizeof(*buf), ctx->install_file); if(!len) return S_OK; for(key = buf; *key; key += strlenW(key)+1) { if(!strcmpiW(key, runW)) { WCHAR *cmd; size_t size; len = GetPrivateProfileStringW(sect_name, runW, NULL, val, sizeof(val)/sizeof(*val), ctx->install_file); TRACE("Run %s\n", debugstr_w(val)); expand_command(ctx, val, NULL, &size); cmd = heap_alloc(size*sizeof(WCHAR)); if(!cmd) heap_free(cmd); expand_command(ctx, val, cmd, &size); hres = RunSetupCommandW(ctx->hwnd, cmd, NULL, ctx->tmp_dir, NULL, NULL, 0, NULL); heap_free(cmd); if(FAILED(hres)) return hres; }else { FIXME("Unsupported hook %s\n", debugstr_w(key)); return E_NOTIMPL; } } return S_OK; }
/** * pm_execute * @params * int should_wait - Indicates if this execute should be inline or asynchronous * const char* command - The command to run * const char* cd - Run in this directory unless it's a NULL pointer * int nice - Special nice level * const char** env - Environment variables to run in the shell * @output pid_t pid - output pid of the new process **/ pid_t pm_execute(int should_wait, const char* command, const char *cd, int nice, const char** env) { // Setup execution char **command_argv = {0}; int command_argc = 0; int running_script = 0; if (expand_command((const char*)str_chomp(command), &command_argc, &command_argv, &running_script)) ; command_argv[command_argc] = 0; // Now actually RUN it! pid_t pid; if (should_wait) pid = vfork(); else pid = fork(); switch (pid) { case -1: return -1; case 0: { pm_setup_signal_handlers(); if (cd != NULL && cd[0] != '\0') chdir(cd); else chdir("/tmp"); if (execve((const char*)command_argv[0], command_argv, (char* const*) env) < 0) { printf("execve failed because: %s\n", strerror(errno)); exit(-1); } } default: // In parent process if (nice != INT_MAX && setpriority(PRIO_PROCESS, pid, nice) < 0) ; return pid; } }
/** * pm_execute * @params * int should_wait - Indicates if this execute should be inline or asynchronous * const char* command - The command to run * const char* cd - Run in this directory unless it's a NULL pointer * int nice - Special nice level * const char** env - Environment variables to run in the shell * @output pid_t pid - output pid of the new process **/ pid_t pm_execute( int should_wait, const char* command, const char *cd, int nice, const char** env, int *child_stdin, const char* p_stdout, const char *p_stderr ) { // Setup execution char **command_argv = {0}; int command_argc = 0; int running_script = 0; int countdown = 200; // If there is nothing here, don't run anything :) if (strlen(command) == 0) return -1; char* chomped_string = str_chomp(command); char* safe_chomped_string = str_safe_quote(chomped_string); if (expand_command((const char*)safe_chomped_string, &command_argc, &command_argv, &running_script, env)) ; command_argv[command_argc] = 0; // Now actually RUN it! pid_t pid; #if USE_PIPES int child_fd[2]; if ( pipe(child_fd) < 0 ) {// Create a pipe to the child (do we need this? I doubt it) perror("pipe failed"); } // Setup the stdin so the parent can communicate! (*child_stdin) = child_fd[0]; #endif // Let's name it so we can get to it later int child_dev_null; #if DEBUG if ((child_dev_null = open("debug.log", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { syslog(LOG_ERR, "babysitter (fatal): Could not open debug.log: errno: %d\n", errno); }; #else if ((child_dev_null = open("/dev/null", O_RDWR)) < 0) { syslog(LOG_ERR, "babysitter (fatal): Could not open /dev/null: errno: %d\n", errno); }; #endif // Setup fork pm_setup_fork(); if (should_wait) pid = vfork(); else pid = fork(); switch (pid) { case -1: return -1; case 0: { // Child process pm_setup_child(); if (cd != NULL && cd[0] != '\0') safe_chdir(cd); else safe_chdir("/tmp"); int child_stdout, child_stderr; // Set everything to dev/null first child_stdout = child_stderr = child_dev_null; // If we've passed in a stdout filename, then open it if(p_stdout) if ((child_stdout = open(p_stdout, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { perror("child stdout"); child_stdout = child_dev_null; } // If we've been passed a stderr filename, then open that if(p_stderr) if ((child_stderr = open(p_stderr, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { perror("child stderr"); child_stderr = child_dev_null; } // Parent doesn't write anything to the child, so just close this right away // REDIRECT TO DEV/NULL // Replace the stdout/stderr with the child_write fd #if USE_PIPES if (dup2(child_fd[0], STDIN_FILENO) < 0) FATAL_ERROR("could not dup STDIN_FILENO", -1); close(child_fd[1]); // We are using a different stdout #endif #if DEBUG #else // Setup the different stdout/stderr if (dup2(child_stdout, STDOUT_FILENO) < 0) FATAL_ERROR("could not dup STDOUT_FILENO", -1); if (dup2(child_stderr, STDERR_FILENO) < 0) FATAL_ERROR("could not dup STDERR_FILENO", -1); if (child_stdout != child_dev_null) close(child_stdout); if (child_stderr != child_dev_null) close(child_stderr); #endif if (execve((const char*)command_argv[0], command_argv, (char* const*) env) < 0) { perror("execve"); exit(-1); } } default: // In parent process // set the stdout back close(child_dev_null); // Child write never gets used outside the child #if USE_PIPES if (dup2(child_fd[1], STDOUT_FILENO) < 0) perror("dup2"); close(child_fd[0]); #endif if (nice != INT_MAX && setpriority(PRIO_PROCESS, pid, nice) < 0) ; if (running_script) { while (countdown > 0) { if (kill(pid, 0) != 0) break; usleep(100); countdown--; } struct stat buffer; if (stat(command_argv[0], &buffer) != 0) { printf("file doesn't exist when it should because: %s\n", strerror(errno)); } if( unlink( command_argv[0] ) != 0 ) perror( "Error deleting file" ); } // These are free'd later, anyway // if (chomped_string) free(chomped_string); // if (safe_chomped_string) free(safe_chomped_string); return pid; } }