MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env) { MVMint64 result = 0, spawn_result = 0; uv_process_t *process = calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i; char * const cmdin = MVM_string_utf8_encode_C_string(tc, cmd); char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = malloc((size + 1) * sizeof(char *)); #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec")); char *args[3]; args[0] = "/c"; { MVMint64 len = strlen(cmdin); MVMint64 i; for (i = 0; i < len; i++) if (cmdin[i] == '/') cmdin[i] = '\\'; } args[1] = cmdin; args[2] = NULL; #else char * const _cmd = "/bin/sh"; char *args[4]; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmdin; args[3] = NULL; #endif INIT_ENV(); SPAWN(_cmd); FREE_ENV(); free(_cwd); #ifdef _WIN32 free(_cmd); #endif free(cmdin); return result; }
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env) { MVMint64 result, spawn_result; uv_process_t process = {0}; uv_process_options_t process_options = {0}; int i; char * const cmdin = MVM_string_utf8_encode_C_string(tc, cmd); char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = malloc((size + 1) * sizeof(char *)); #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec")); char *args[3]; args[0] = "/c"; args[1] = cmdin; args[2] = NULL; #else char * const _cmd = "/bin/sh"; char *args[4]; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmdin; args[3] = NULL; #endif MVMROOT(tc, iter, { MVMString * const equal = MVM_string_ascii_decode(tc, tc->instance->VMString, STR_WITH_LEN("=")); MVMROOT(tc, equal, { MVMString *env_str; i = 0; while(MVM_iter_istrue(tc, iter)) { MVM_repr_shift_o(tc, (MVMObject *)iter); env_str = MVM_string_concatenate(tc, MVM_iterkey_s(tc, iter), equal); env_str = MVM_string_concatenate(tc, env_str, MVM_repr_get_str(tc, MVM_iterval(tc, iter))); _env[i++] = MVM_string_utf8_encode_C_string(tc, env_str); } _env[size] = NULL; }); });
MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env, MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) { MVMint64 result = 0, spawn_result; uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i, process_still_running; char * const cmdin = MVM_string_utf8_c8_encode_C_string(tc, cmd); char * const _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); char **_env = MVM_malloc((size + 1) * sizeof(char *)); MVMIter *iter; #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec")); char *args[3]; args[0] = "/c"; args[1] = cmdin; args[2] = NULL; #else char * const _cmd = "/bin/sh"; char *args[4]; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmdin; args[3] = NULL; #endif MVMROOT(tc, in, { MVMROOT(tc, out, { MVMROOT(tc, err, { iter = (MVMIter *)MVM_iter(tc, env); INIT_ENV(); }); });
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMObject *argv, MVMString *cwd, MVMObject *env) { MVMint64 result = 0, spawn_result = 0; uv_process_t *process = calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i; char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = malloc((size + 1) * sizeof(char *)); const MVMuint64 arg_size = MVM_repr_elems(tc, argv); char **args = malloc((arg_size + 1) * sizeof(char *)); MVMRegister reg; i = 0; while(i < arg_size) { REPR(argv)->pos_funcs.at_pos(tc, STABLE(argv), argv, OBJECT_BODY(argv), i, ®, MVM_reg_obj); args[i++] = MVM_string_utf8_encode_C_string(tc, MVM_repr_get_str(tc, reg.o)); } args[arg_size] = NULL; INIT_ENV(); SPAWN(arg_size ? args[0] : NULL); FREE_ENV(); free(_cwd); i = 0; while(args[i]) free(args[i++]); free(args); return result; }
/* Locates all of the attributes. Puts them onto a flattened, ordered * list of attributes (populating the passed flat_list). Also builds * the index mapping for doing named lookups. Note index is not related * to the storage position. */ static MVMObject * index_mapping_and_flat_list(MVMThreadContext *tc, MVMObject *mro, MVMCPPStructREPRData *repr_data) { MVMInstance *instance = tc->instance; MVMObject *flat_list, *class_list, *attr_map_list; MVMint32 num_classes, i, current_slot = 0; MVMCPPStructNameMap *result; MVMint32 mro_idx = MVM_repr_elems(tc, mro); MVM_gc_root_temp_push(tc, (MVMCollectable **)&mro); flat_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type); MVM_gc_root_temp_push(tc, (MVMCollectable **)&flat_list); class_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type); MVM_gc_root_temp_push(tc, (MVMCollectable **)&class_list); attr_map_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type); MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_map_list); /* Walk through the parents list. */ while (mro_idx) { /* Get current class in MRO. */ MVMObject *type_info = MVM_repr_at_pos_o(tc, mro, --mro_idx); MVMObject *current_class = MVM_repr_at_pos_o(tc, type_info, 0); /* Get its local parents; make sure we're not doing MI. */ MVMObject *parents = MVM_repr_at_pos_o(tc, type_info, 2); MVMint32 num_parents = MVM_repr_elems(tc, parents); if (num_parents <= 1) { /* Get attributes and iterate over them. */ MVMObject *attributes = MVM_repr_at_pos_o(tc, type_info, 1); MVMIter * const attr_iter = (MVMIter *)MVM_iter(tc, attributes); MVMObject *attr_map = NULL; if (MVM_iter_istrue(tc, attr_iter)) { MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_iter); attr_map = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_hash_type); MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_map); } while (MVM_iter_istrue(tc, attr_iter)) { MVMObject *current_slot_obj = MVM_repr_box_int(tc, MVM_hll_current(tc)->int_box_type, current_slot); MVMObject *attr, *name_obj; MVMString *name; MVM_repr_shift_o(tc, (MVMObject *)attr_iter); /* Get attribute. */ attr = MVM_iterval(tc, attr_iter); /* Get its name. */ name_obj = MVM_repr_at_key_o(tc, attr, instance->str_consts.name); name = MVM_repr_get_str(tc, name_obj); MVM_repr_bind_key_o(tc, attr_map, name, current_slot_obj); current_slot++; /* Push attr onto the flat list. */ MVM_repr_push_o(tc, flat_list, attr); } if (attr_map) { MVM_gc_root_temp_pop_n(tc, 2); } /* Add to class list and map list. */ MVM_repr_push_o(tc, class_list, current_class); MVM_repr_push_o(tc, attr_map_list, attr_map); } else { MVM_exception_throw_adhoc(tc, "CPPStruct representation does not support multiple inheritance"); } } MVM_gc_root_temp_pop_n(tc, 4); /* We can now form the name map. */ num_classes = MVM_repr_elems(tc, class_list); result = (MVMCPPStructNameMap *) MVM_malloc(sizeof(MVMCPPStructNameMap) * (1 + num_classes)); for (i = 0; i < num_classes; i++) { result[i].class_key = MVM_repr_at_pos_o(tc, class_list, i); result[i].name_map = MVM_repr_at_pos_o(tc, attr_map_list, i); } /* set the end to be NULL, it's useful for iteration. */ result[i].class_key = NULL; repr_data->name_to_index_mapping = result; return flat_list; }
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMObject *argv, MVMString *cwd, MVMObject *env, MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) { MVMint64 result = 0, spawn_result; uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i; char * const _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = MVM_malloc((size + 1) * sizeof(char *)); const MVMuint64 arg_size = MVM_repr_elems(tc, argv); char **args = MVM_malloc((arg_size + 1) * sizeof(char *)); MVMRegister reg; i = 0; while(i < arg_size) { REPR(argv)->pos_funcs.at_pos(tc, STABLE(argv), argv, OBJECT_BODY(argv), i, ®, MVM_reg_obj); args[i++] = MVM_string_utf8_c8_encode_C_string(tc, MVM_repr_get_str(tc, reg.o)); } args[arg_size] = NULL; INIT_ENV(); setup_process_stdio(tc, in, process, &process_stdio[0], 0, flags, "spawn"); setup_process_stdio(tc, out, process, &process_stdio[1], 1, flags >> 3, "spawn"); setup_process_stdio(tc, err, process, &process_stdio[2], 2, flags >> 6, "spawn"); process_options.stdio = process_stdio; process_options.file = arg_size ? args[0] : NULL; process_options.args = args; process_options.cwd = _cwd; process_options.flags = UV_PROCESS_WINDOWS_HIDE; process_options.env = _env; process_options.stdio_count = 3; process_options.exit_cb = spawn_on_exit; if (flags & (MVM_PIPE_CAPTURE_IN | MVM_PIPE_CAPTURE_OUT | MVM_PIPE_CAPTURE_ERR)) { process->data = MVM_calloc(1, sizeof(MVMint64)); uv_ref((uv_handle_t *)process); spawn_result = uv_spawn(tc->loop, process, &process_options); if (spawn_result) result = spawn_result; } else { process->data = &result; uv_ref((uv_handle_t *)process); spawn_result = uv_spawn(tc->loop, process, &process_options); if (spawn_result) result = spawn_result; else uv_run(tc->loop, UV_RUN_DEFAULT); } FREE_ENV(); MVM_free(_cwd); uv_unref((uv_handle_t *)process); i = 0; while(args[i]) MVM_free(args[i++]); MVM_free(args); return result; }
MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env, MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) { MVMint64 result = 0, spawn_result; uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i; char * const cmdin = MVM_string_utf8_c8_encode_C_string(tc, cmd); char * const _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = MVM_malloc((size + 1) * sizeof(char *)); #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec")); char *args[3]; args[0] = "/c"; args[1] = cmdin; args[2] = NULL; #else char * const _cmd = "/bin/sh"; char *args[4]; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmdin; args[3] = NULL; #endif INIT_ENV(); setup_process_stdio(tc, in, process, &process_stdio[0], 0, flags, "shell"); setup_process_stdio(tc, out, process, &process_stdio[1], 1, flags >> 3, "shell"); setup_process_stdio(tc, err, process, &process_stdio[2], 2, flags >> 6, "shell"); process_options.stdio = process_stdio; process_options.file = _cmd; process_options.args = args; process_options.cwd = _cwd; process_options.flags = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | UV_PROCESS_WINDOWS_HIDE; process_options.env = _env; process_options.stdio_count = 3; process_options.exit_cb = spawn_on_exit; if (flags & (MVM_PIPE_CAPTURE_IN | MVM_PIPE_CAPTURE_OUT | MVM_PIPE_CAPTURE_ERR)) { process->data = MVM_calloc(1, sizeof(MVMint64)); uv_ref((uv_handle_t *)process); spawn_result = uv_spawn(tc->loop, process, &process_options); if (spawn_result) result = spawn_result; } else { process->data = &result; uv_ref((uv_handle_t *)process); spawn_result = uv_spawn(tc->loop, process, &process_options); if (spawn_result) result = spawn_result; else uv_run(tc->loop, UV_RUN_DEFAULT); } FREE_ENV(); MVM_free(_cwd); #ifdef _WIN32 MVM_free(_cmd); #endif MVM_free(cmdin); uv_unref((uv_handle_t *)process); return result; }
MVMObject * MVM_file_openpipe(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env, MVMString *err_path) { MVMint64 spawn_result = 0; uv_process_t *process = calloc(1, sizeof(uv_process_t)); uv_process_options_t process_options = {0}; uv_stdio_container_t process_stdio[3]; int i; int status; int readable = 1; uv_pipe_t *out, *in; char * const cmdin = MVM_string_utf8_encode_C_string(tc, cmd); char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd); const MVMuint64 size = MVM_repr_elems(tc, env); MVMIter * const iter = (MVMIter *)MVM_iter(tc, env); char **_env = malloc((size + 1) * sizeof(char *)); #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec")); char *args[3]; args[0] = "/c"; { MVMint64 len = strlen(cmdin); MVMint64 i; for (i = 0; i < len; i++) if (cmdin[i] == '/') cmdin[i] = '\\'; } args[1] = cmdin; args[2] = NULL; #else char * const _cmd = "/bin/sh"; char *args[4]; args[0] = "/bin/sh"; args[1] = "-c"; args[2] = cmdin; args[3] = NULL; #endif INIT_ENV(); /* Making openpipe distinguish between :rp and :wp and all other options * is left as an excercise for the reader. readable = strncmp(cmdin, "/usr/bin/wc", 11) != 0; */ if (readable) { /* We want to read from the child's stdout. */ out = malloc(sizeof(uv_pipe_t)); uv_pipe_init(tc->loop, out, 0); uv_pipe_open(out, 0); process_stdio[0].flags = UV_INHERIT_FD; // child's stdin process_stdio[0].data.fd = 0; process_stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; // child's stdout process_stdio[1].data.stream = (uv_stream_t*)out; } else { /* We want to print to the child's stdin. */ in = malloc(sizeof(uv_pipe_t)); uv_pipe_init(tc->loop, in, 0); uv_pipe_open(in, 1); process_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; // child's stdin process_stdio[0].data.stream = (uv_stream_t*)in; process_stdio[1].flags = UV_INHERIT_FD; // child's stdout process_stdio[1].data.fd = 1; } process_stdio[2].flags = UV_INHERIT_FD; // child's stderr process_stdio[2].data.fd = 2; process_options.stdio = process_stdio; process_options.file = _cmd; process_options.args = args; process_options.cwd = _cwd; process_options.flags = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | UV_PROCESS_WINDOWS_HIDE; process_options.env = _env; process_options.stdio_count = 3; process_options.exit_cb = spawn_on_exit; uv_ref((uv_handle_t *)process); spawn_result = uv_spawn(tc->loop, process, &process_options); if (spawn_result) { FREE_ENV(); free(_cwd); free(cmdin); uv_unref((uv_handle_t *)process); MVM_exception_throw_adhoc(tc, "Failed to open pipe: %d", errno); } FREE_ENV(); free(_cwd); free(cmdin); uv_unref((uv_handle_t *)process); return MVM_io_syncpipe(tc, (uv_stream_t *)(readable ? out : in), process); }