/** * Invoke the main function. */ int invoke_as_new_process(ProgramInvoker* invoker) { char line[4096]; build_command_line(invoker,line); int ret=system(line); return ret; }
static bool ffmpeg_mux_start(void *data) { struct ffmpeg_muxer *stream = data; obs_data_t *settings; struct dstr cmd; const char *path; if (!obs_output_can_begin_data_capture(stream->output, 0)) return false; if (!obs_output_initialize_encoders(stream->output, 0)) return false; settings = obs_output_get_settings(stream->output); path = obs_data_get_string(settings, "path"); dstr_copy(&stream->path, path); dstr_replace(&stream->path, "\"", "\"\""); obs_data_release(settings); build_command_line(stream, &cmd); stream->pipe = os_process_pipe_create(cmd.array, "w"); dstr_free(&cmd); if (!stream->pipe) { warn("Failed to create process pipe"); return false; } /* write headers and start capture */ stream->active = true; stream->capturing = true; obs_output_begin_data_capture(stream->output, 0); info("Writing file '%s'...", stream->path.array); return true; }
int main(int argc, char *argv[]) { PROCESS_INFORMATION pi; STARTUPINFO si; DWORD exitcode; int uses_redirection, in_quotes, i; static const char cmd_prefix[] = "cmd.exe /c "; // build the new command line build_command_line(argc, argv); // do we use redirection? if so, use cmd.exe uses_redirection = FALSE; in_quotes = FALSE; for (i = 0; command_line[i]; i++) { if (command_line[i] == '\"') in_quotes = !in_quotes; if (!in_quotes && strchr("|<>", command_line[i])) uses_redirection = TRUE; } if (uses_redirection) { memmove(command_line + strlen(cmd_prefix), command_line, strlen(command_line) + 1); memcpy(command_line, cmd_prefix, strlen(cmd_prefix)); } if (PRINT_COMMAND_LINE) printf("%s\n", command_line); // create the process information structures memset(&si, 0, sizeof(si)); si.cb = sizeof(si); memset(&pi, 0, sizeof(pi)); // create and execute the process if (!CreateProcess(NULL, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) || pi.hProcess == INVALID_HANDLE_VALUE) return -101; // block until done and fetch the error code WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); // clean up the handles CloseHandle(pi.hProcess); CloseHandle(pi.hThread); // return the child's error code return exitcode; }
/** * \brief Calls the tokenize program in Cassys * * Tokenize is called with target text_name and options --word_by_word, --alphabet=alphabet_name, --token=token_txt_name if * if token_txt_name is not NULL. For more information about tokenize, see the unitex manual. * * \param [in/out] text_name the name of the text * \param [in] alphabet the name of the alphabet * \param [in/out] token_txt_name the file containing all the of the text or * * * * */ int launch_tokenize_in_Cassys(const char *text_name, const char *alphabet_name, const char *token_txt_name, Encoding encoding_output,int bom_output,int mask_encoding_compatibility_input){ fprintf(stdout,"Launch tokenize in Cassys\n"); ProgramInvoker *invoker = new_ProgramInvoker(main_Tokenize,"main_Tokenize"); char tmp[FILENAME_MAX]; { tmp[0]=0; get_reading_encoding_text(tmp,sizeof(tmp)-1,mask_encoding_compatibility_input); if (tmp[0] != '\0') { add_argument(invoker,"-k"); add_argument(invoker,tmp); } tmp[0]=0; get_writing_encoding_text(tmp,sizeof(tmp)-1,encoding_output,bom_output); if (tmp[0] != '\0') { add_argument(invoker,"-q"); add_argument(invoker,tmp); } } // add the alphabet char alphabet_argument[FILENAME_MAX + 11]; sprintf(alphabet_argument, "--alphabet=%s", alphabet_name); add_argument(invoker, alphabet_argument); // Tokenize word by word add_argument(invoker, "--word_by_word"); // add the target text file add_argument(invoker,text_name); // if a token.txt file already exists, use it if(token_txt_name != NULL){ char token_argument[FILENAME_MAX + 9]; sprintf(token_argument,"--tokens=%s",token_txt_name); add_argument(invoker,token_argument); } char line_command[4096]; build_command_line(invoker, line_command); fprintf(stdout, "%s\n", line_command); int result = invoke(invoker); free_ProgramInvoker(invoker); return result; }
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, unsigned long initrd_addr, unsigned long initrd_size) { struct setup_header *hdr = &setup_base->hdr; int bootproto = get_boot_protocol(hdr); setup_base->e820_entries = install_e820_map( ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); if (bootproto == 0x0100) { setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET; } if (bootproto >= 0x0200) { hdr->type_of_loader = 8; if (initrd_addr) { printf("Initial RAM disk at linear address " "0x%08lx, size %ld bytes\n", initrd_addr, initrd_size); hdr->ramdisk_image = initrd_addr; hdr->ramdisk_size = initrd_size; } } if (bootproto >= 0x0201) { hdr->heap_end_ptr = HEAP_END_OFFSET; hdr->loadflags |= HEAP_FLAG; } if (cmd_line) { if (bootproto >= 0x0202) { hdr->cmd_line_ptr = (uintptr_t)cmd_line; } else if (bootproto >= 0x0200) { setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; setup_base->screen_info.cl_offset = (uintptr_t)cmd_line - (uintptr_t)setup_base; hdr->setup_move_size = 0x9100; } /* build command line at COMMAND_LINE_OFFSET */ build_command_line(cmd_line, auto_boot); } setup_video(&setup_base->screen_info); return 0; }
OPENVPN_EXPORT openvpn_plugin_handle_t openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[]) { struct down_root_context *context; /* * Allocate our context */ context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context)); if (!context) goto error; context->foreground_fd = -1; /* * Intercept the --up and --down callbacks */ *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN); /* * Make sure we have two string arguments: the first is the .so name, * the second is the script command. */ if (string_array_len (argv) < 2) { fprintf (stderr, "DOWN-ROOT: need down script command\n"); goto error; } /* * Save our argument in context */ context->command = build_command_line (&argv[1]); /* * Get verbosity level from environment */ { const char *verb_string = get_env ("verb", envp); if (verb_string) context->verb = atoi (verb_string); } return (openvpn_plugin_handle_t) context; error: free_context (context); return NULL; }
command_line_up get_command_line (enum command_control_type type, const char *arg) { /* Allocate and build a new command line structure. */ command_line_up cmd (build_command_line (type, arg)); /* Read in the body of this command. */ if (recurse_read_control_structure (read_next_line, cmd.get (), 0, 0) == invalid_control) { warning (_("Error reading in canned sequence of commands.")); return NULL; } return cmd; }
/** * \brief Calls the Concord program in Cassys * * Concord is called with target index_file and options * --merge=text_name, --alphabet=alphabet_name. * * For more information about Concord, see the unitex manual. * * \param [in/out] text_name the name of the text * \param [in] alphabet the name of the alphabet * \param [in] index_file file containing all the matches found by locate * */ int launch_concord_in_Cassys(const char *text_name, const char *index_file, const char *alphabet_name, Encoding encoding_output,int bom_output,int mask_encoding_compatibility_input){ ProgramInvoker *invoker = new_ProgramInvoker(main_Concord, "main_Concord"); add_argument(invoker,index_file); char tmp[FILENAME_MAX]; { tmp[0]=0; get_reading_encoding_text(tmp,sizeof(tmp)-1,mask_encoding_compatibility_input); if (tmp[0] != '\0') { add_argument(invoker,"-k"); add_argument(invoker,tmp); } tmp[0]=0; get_writing_encoding_text(tmp,sizeof(tmp)-1,encoding_output,bom_output); if (tmp[0] != '\0') { add_argument(invoker,"-q"); add_argument(invoker,tmp); } } char text_argument[FILENAME_MAX+7]; sprintf(text_argument,"--merge=%s",text_name); add_argument(invoker,text_argument); char alphabet_argument[FILENAME_MAX+11]; sprintf(alphabet_argument,"--alphabet=%s",alphabet_name); char line_command[4096]; build_command_line(invoker, line_command); fprintf(stdout, "%s\n", line_command); int result = invoke(invoker); free_ProgramInvoker(invoker); return result; }
struct command_line * get_command_line (enum command_control_type type, char *arg) { struct command_line *cmd; struct cleanup *old_chain = NULL; /* Allocate and build a new command line structure. */ cmd = build_command_line (type, arg); old_chain = make_cleanup_free_command_lines (&cmd); /* Read in the body of this command. */ if (recurse_read_control_structure (read_next_line, cmd, 0, 0) == invalid_control) { warning (_("Error reading in canned sequence of commands.")); do_cleanups (old_chain); return NULL; } discard_cleanups (old_chain); return cmd; }
/* * Background process -- runs with privilege. */ static void down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb) { const char *p[3]; char *command_line = NULL; char *argv_cat = NULL; int i; /* * Do initialization */ if (DEBUG (verb)) fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", command); /* * Tell foreground that we initialized successfully */ if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1) { fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [1]\n"); goto done; } /* * Build command line */ if (string_array_len (argv) >= 2) argv_cat = build_command_line (&argv[1]); else argv_cat = build_command_line (NULL); p[0] = command; p[1] = argv_cat; p[2] = NULL; command_line = build_command_line (p); /* * Save envp in environment */ for (i = 0; envp[i]; ++i) { putenv ((char *)envp[i]); } /* * Event loop */ while (1) { int command_code; int status; /* get a command from foreground process */ command_code = recv_control (fd); if (DEBUG (verb)) fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code); switch (command_code) { case COMMAND_RUN_SCRIPT: status = system (command_line); if (system_ok (status)) /* Succeeded */ { if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1) { fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [2]\n"); goto done; } } else /* Failed */ { if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1) { fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [3]\n"); goto done; } } break; case COMMAND_EXIT: goto done; case -1: fprintf (stderr, "DOWN-ROOT: BACKGROUND: read error on command channel\n"); goto done; default: fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n", command_code); goto done; } } done: if (argv_cat) free (argv_cat); if (command_line) free (command_line); if (DEBUG (verb)) fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n"); return; }
static enum misc_command_type process_next_line (char *p, struct command_line **command, int parse_commands, void (*validator)(char *, void *), void *closure) { char *p_end; char *p_start; int not_handled = 0; /* Not sure what to do here. */ if (p == NULL) return end_command; /* Strip trailing whitespace. */ p_end = p + strlen (p); while (p_end > p && (p_end[-1] == ' ' || p_end[-1] == '\t')) p_end--; p_start = p; /* Strip leading whitespace. */ while (p_start < p_end && (*p_start == ' ' || *p_start == '\t')) p_start++; /* 'end' is always recognized, regardless of parse_commands value. We also permit whitespace before end and after. */ if (p_end - p_start == 3 && !strncmp (p_start, "end", 3)) return end_command; if (parse_commands) { /* If commands are parsed, we skip initial spaces. Otherwise, which is the case for Python commands and documentation (see the 'document' command), spaces are preserved. */ p = p_start; /* Blanks and comments don't really do anything, but we need to distinguish them from else, end and other commands which can be executed. */ if (p_end == p || p[0] == '#') return nop_command; /* Is the else clause of an if control structure? */ if (p_end - p == 4 && !strncmp (p, "else", 4)) return else_command; /* Check for while, if, break, continue, etc and build a new command line structure for them. */ if ((p_end - p >= 14 && !strncmp (p, "while-stepping", 14)) || (p_end - p >= 8 && !strncmp (p, "stepping", 8)) || (p_end - p >= 2 && !strncmp (p, "ws", 2))) { /* Because validate_actionline and encode_action lookup command's line as command, we need the line to include 'while-stepping'. For 'ws' alias, the command will have 'ws', not expanded to 'while-stepping'. This is intentional -- we don't really want frontend to send a command list with 'ws', and next break-info returning command line with 'while-stepping'. This should work, but might cause the breakpoint to be marked as changed while it's actually not. */ *command = build_command_line (while_stepping_control, p); } else if (p_end - p > 5 && !strncmp (p, "while", 5)) { char *first_arg; first_arg = p + 5; while (first_arg < p_end && isspace (*first_arg)) first_arg++; *command = build_command_line (while_control, first_arg); } else if (p_end - p > 2 && !strncmp (p, "if", 2)) { char *first_arg; first_arg = p + 2; while (first_arg < p_end && isspace (*first_arg)) first_arg++; *command = build_command_line (if_control, first_arg); } else if (p_end - p >= 8 && !strncmp (p, "commands", 8)) { char *first_arg; first_arg = p + 8; while (first_arg < p_end && isspace (*first_arg)) first_arg++; *command = build_command_line (commands_control, first_arg); } else if (p_end - p == 6 && !strncmp (p, "python", 6)) { /* Note that we ignore the inline "python command" form here. */ *command = build_command_line (python_control, ""); } else if (p_end - p == 10 && !strncmp (p, "loop_break", 10)) { *command = (struct command_line *) xmalloc (sizeof (struct command_line)); (*command)->next = NULL; (*command)->line = NULL; (*command)->control_type = break_control; (*command)->body_count = 0; (*command)->body_list = NULL; } else if (p_end - p == 13 && !strncmp (p, "loop_continue", 13)) { *command = (struct command_line *) xmalloc (sizeof (struct command_line)); (*command)->next = NULL; (*command)->line = NULL; (*command)->control_type = continue_control; (*command)->body_count = 0; (*command)->body_list = NULL; } else not_handled = 1; } if (!parse_commands || not_handled) { /* A normal command. */ *command = (struct command_line *) xmalloc (sizeof (struct command_line)); (*command)->next = NULL; (*command)->line = savestring (p, p_end - p); (*command)->control_type = simple_control; (*command)->body_count = 0; (*command)->body_list = NULL; } if (validator) { volatile struct gdb_exception ex; TRY_CATCH (ex, RETURN_MASK_ALL) { validator ((*command)->line, closure); } if (ex.reason < 0) { xfree (*command); throw_exception (ex); } }
/** * \brief Calls the Locate program in Cassys * * Locate is called with target the transducer file name of transudcer and options * --text=text_name, --alphabet=alphabet_name, --longest_matches, --all and --merge or --replace * depending of the output policy of the transducer. * * For more information about Locate, see the unitex manual. * * \param [in/out] text_name the name of the text * \param [in] alphabet the name of the alphabet * \param [in] transducer structure containing information about the transducer to be applied * */ int launch_locate_in_Cassys(const char *text_name, const transducer *transducer, const char* alphabet_name, const char*negation_operator, Encoding encoding_output,int bom_output,int mask_encoding_compatibility_input){ ProgramInvoker *invoker = new_ProgramInvoker(main_Locate, "main_Locate"); char tmp[FILENAME_MAX]; { tmp[0]=0; get_reading_encoding_text(tmp,sizeof(tmp)-1,mask_encoding_compatibility_input); if (tmp[0] != '\0') { add_argument(invoker,"-k"); add_argument(invoker,tmp); } tmp[0]=0; get_writing_encoding_text(tmp,sizeof(tmp)-1,encoding_output,bom_output); if (tmp[0] != '\0') { add_argument(invoker,"-q"); add_argument(invoker,tmp); } } add_argument(invoker, transducer->transducer_file_name); // add the text char text_argument[FILENAME_MAX+7]; sprintf(text_argument,"--text=%s",text_name); add_argument(invoker, text_argument); // add the merge or replace option switch (transducer ->output_policy) { case MERGE_OUTPUTS: add_argument(invoker,"--merge"); break; case REPLACE_OUTPUTS: add_argument(invoker,"--replace"); break; default: add_argument(invoker,"--ignore"); break; } // add the alphabet char alphabet_argument[FILENAME_MAX+11]; sprintf(alphabet_argument,"--alphabet=%s",alphabet_name); add_argument(invoker, alphabet_argument); // look for the longest match argument add_argument(invoker, "--longest_matches"); // look for all the occurrences add_argument(invoker, "--all"); if ((*negation_operator) != 0) { char negation_operator_argument[0x40]; sprintf(negation_operator_argument,"--negation_operator=%s",negation_operator); add_argument(invoker,negation_operator_argument); } char line_command[4096]; build_command_line(invoker,line_command); fprintf(stdout, "%s\n",line_command); int result = invoke(invoker); free_ProgramInvoker(invoker); return result; }
/*********************************************************************** * main */ int main( int argc, char *argv[] ) { DWORD count; HINSTANCE16 instance; LOADPARAMS16 params; WORD showCmd[2]; char buffer[MAX_PATH]; STARTUPINFOA info; char *cmdline, *appname, **first_arg; char *p; if (!argv[1]) usage(); if (!strcmp( argv[1], "--app-name" )) { if (!(appname = argv[2])) usage(); first_arg = argv + 3; } else { if (!SearchPathA( NULL, argv[1], ".exe", sizeof(buffer), buffer, NULL )) { WINE_MESSAGE( "winevdm: unable to exec '%s': file not found\n", argv[1] ); ExitProcess(1); } appname = buffer; first_arg = argv + 1; } if (*first_arg) first_arg++; /* skip program name */ cmdline = build_command_line( first_arg ); if (WINE_TRACE_ON(winevdm)) { int i; WINE_TRACE( "GetCommandLine = '%s'\n", GetCommandLineA() ); WINE_TRACE( "appname = '%s'\n", appname ); WINE_TRACE( "cmdline = '%.*s'\n", cmdline[0], cmdline+1 ); for (i = 0; argv[i]; i++) WINE_TRACE( "argv[%d]: '%s'\n", i, argv[i] ); } GetStartupInfoA( &info ); showCmd[0] = 2; showCmd[1] = (info.dwFlags & STARTF_USESHOWWINDOW) ? info.wShowWindow : SW_SHOWNORMAL; params.hEnvironment = 0; params.cmdLine = MapLS( cmdline ); params.showCmd = MapLS( showCmd ); params.reserved = 0; RestoreThunkLock(1); /* grab the Win16 lock */ /* some programs assume mmsystem is always present */ LoadLibrary16( "gdi.exe" ); LoadLibrary16( "user.exe" ); LoadLibrary16( "mmsystem.dll" ); if ((instance = LoadModule16( appname, ¶ms )) < 32) { if (instance == 11) { /* first see if it is a .pif file */ if( ( p = strrchr( appname, '.' )) && !strcasecmp( p, ".pif")) pif_cmd( appname, cmdline + 1); else { /* try DOS format */ /* loader expects arguments to be regular C strings */ start_dos_exe( appname, cmdline + 1 ); } /* if we get back here it failed */ instance = GetLastError(); } WINE_MESSAGE( "winevdm: can't exec '%s': ", appname ); switch (instance) { case 2: WINE_MESSAGE("file not found\n" ); break; case 11: WINE_MESSAGE("invalid program file\n" ); break; default: WINE_MESSAGE("error=%d\n", instance ); break; } ExitProcess(instance); } /* wait forever; the process will be killed when the last task exits */ ReleaseThunkLock( &count ); Sleep( INFINITE ); return 0; }
static enum misc_command_type process_next_line (char *p, struct command_line **command, int parse_commands, void (*validator)(char *, void *), void *closure) { char *p_end; char *p_start; int not_handled = 0; /* Not sure what to do here. */ if (p == NULL) return end_command; /* Strip trailing whitespace. */ p_end = p + strlen (p); while (p_end > p && (p_end[-1] == ' ' || p_end[-1] == '\t')) p_end--; p_start = p; /* Strip leading whitespace. */ while (p_start < p_end && (*p_start == ' ' || *p_start == '\t')) p_start++; /* 'end' is always recognized, regardless of parse_commands value. We also permit whitespace before end and after. */ if (p_end - p_start == 3 && startswith (p_start, "end")) return end_command; if (parse_commands) { /* Resolve command abbreviations (e.g. 'ws' for 'while-stepping'). */ const char *cmd_name = p; struct cmd_list_element *cmd = lookup_cmd_1 (&cmd_name, cmdlist, NULL, 1); cmd_name = skip_spaces (cmd_name); bool inline_cmd = *cmd_name != '\0'; /* If commands are parsed, we skip initial spaces. Otherwise, which is the case for Python commands and documentation (see the 'document' command), spaces are preserved. */ p = p_start; /* Blanks and comments don't really do anything, but we need to distinguish them from else, end and other commands which can be executed. */ if (p_end == p || p[0] == '#') return nop_command; /* Is the else clause of an if control structure? */ if (p_end - p == 4 && startswith (p, "else")) return else_command; /* Check for while, if, break, continue, etc and build a new command line structure for them. */ if (command_name_equals (cmd, "while-stepping")) { /* Because validate_actionline and encode_action lookup command's line as command, we need the line to include 'while-stepping'. For 'ws' alias, the command will have 'ws', not expanded to 'while-stepping'. This is intentional -- we don't really want frontend to send a command list with 'ws', and next break-info returning command line with 'while-stepping'. This should work, but might cause the breakpoint to be marked as changed while it's actually not. */ *command = build_command_line (while_stepping_control, p); } else if (command_name_equals (cmd, "while")) { *command = build_command_line (while_control, line_first_arg (p)); } else if (command_name_equals (cmd, "if")) { *command = build_command_line (if_control, line_first_arg (p)); } else if (command_name_equals (cmd, "commands")) { *command = build_command_line (commands_control, line_first_arg (p)); } else if (command_name_equals (cmd, "python") && !inline_cmd) { /* Note that we ignore the inline "python command" form here. */ *command = build_command_line (python_control, ""); } else if (command_name_equals (cmd, "compile") && !inline_cmd) { /* Note that we ignore the inline "compile command" form here. */ *command = build_command_line (compile_control, ""); (*command)->control_u.compile.scope = COMPILE_I_INVALID_SCOPE; } else if (command_name_equals (cmd, "guile") && !inline_cmd) { /* Note that we ignore the inline "guile command" form here. */ *command = build_command_line (guile_control, ""); } else if (p_end - p == 10 && startswith (p, "loop_break")) { *command = XNEW (struct command_line); (*command)->next = NULL; (*command)->line = NULL; (*command)->control_type = break_control; (*command)->body_count = 0; (*command)->body_list = NULL; } else if (p_end - p == 13 && startswith (p, "loop_continue"))
static int posix_spawn_common( bool search_path, pid_t *pid, const char *path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) { STARTUPINFO sinfo; SECURITY_ATTRIBUTES sec; PROCESS_INFORMATION pinfo; char *cmdbuf; char *env_block; DWORD create_flags = CREATE_NO_WINDOW; int ret; int i; unused_parameter(envp); // FIXME cmdbuf = build_command_line(argv); if (!cmdbuf) { return ENOMEM; } env_block = make_env_block(envp); if (!env_block) { free(cmdbuf); return ENOMEM; } memset(&sinfo, 0, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); sinfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; sinfo.wShowWindow = SW_HIDE; memset(&sec, 0, sizeof(sec)); sec.nLength = sizeof(sec); sec.bInheritHandle = TRUE; memset(&pinfo, 0, sizeof(pinfo)); if (attrp->flags & POSIX_SPAWN_SETPGROUP) { create_flags |= CREATE_NEW_PROCESS_GROUP; } // Process any dup(2) actions for (i = 0; i < file_actions->ndups; i++) { struct _posix_spawn_file_dup *dup = &file_actions->dups[i]; HANDLE *target = NULL; DWORD err; switch (dup->target_fd) { case 0: target = &sinfo.hStdInput; break; case 1: target = &sinfo.hStdOutput; break; case 2: target = &sinfo.hStdError; break; } if (!target) { w_log(W_LOG_ERR, "posix_spawn: can't target fd outside range [0-2]\n"); ret = ENOSYS; goto done; } if (*target) { CloseHandle(*target); *target = INVALID_HANDLE_VALUE; } if (!DuplicateHandle(GetCurrentProcess(), dup->local_handle, GetCurrentProcess(), target, 0, TRUE, DUPLICATE_SAME_ACCESS)) { err = GetLastError(); w_log(W_LOG_ERR, "posix_spawn: failed to duplicate handle: %s\n", win32_strerror(err)); ret = map_win32_err(err); goto done; } } // Process any file opening actions for (i = 0; i < file_actions->nopens; i++) { struct _posix_spawn_file_open *op = &file_actions->opens[i]; HANDLE h; HANDLE *target = NULL; switch (op->target_fd) { case 0: target = &sinfo.hStdInput; break; case 1: target = &sinfo.hStdOutput; break; case 2: target = &sinfo.hStdError; break; } if (!target) { w_log(W_LOG_ERR, "posix_spawn: can't target fd outside range [0-2]\n"); ret = ENOSYS; goto done; } h = w_handle_open(op->name, op->flags & ~O_CLOEXEC); if (h == INVALID_HANDLE_VALUE) { ret = errno; w_log(W_LOG_ERR, "posix_spawn: failed to open %s:\n", op->name); goto done; } if (*target) { CloseHandle(*target); } *target = h; } if (!sinfo.hStdInput) { sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); } if (!sinfo.hStdOutput) { sinfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); } if (!sinfo.hStdError) { sinfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); } if (!CreateProcess(search_path ? NULL : path, cmdbuf, &sec, &sec, TRUE, create_flags, env_block, attrp->working_dir, &sinfo, &pinfo)) { w_log(W_LOG_ERR, "CreateProcess: `%s`: (cwd=%s) %s\n", cmdbuf, attrp->working_dir ? attrp->working_dir : "<process cwd>", win32_strerror(GetLastError())); ret = EACCES; } else { *pid = (pid_t)pinfo.dwProcessId; // Record the pid -> handle mapping for later wait/reap pthread_mutex_lock(&child_proc_lock); if (!child_procs) { child_procs = w_ht_new(2, NULL); } w_ht_set(child_procs, pinfo.dwProcessId, w_ht_ptr_val(pinfo.hProcess)); pthread_mutex_unlock(&child_proc_lock); CloseHandle(pinfo.hThread); ret = 0; } done: free(cmdbuf); free(env_block); // If we manufactured any handles, close them out now if (sinfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE)) { CloseHandle(sinfo.hStdInput); } if (sinfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE)) { CloseHandle(sinfo.hStdOutput); } if (sinfo.hStdError != GetStdHandle(STD_ERROR_HANDLE)) { CloseHandle(sinfo.hStdError); } return ret; }