void spawn_helper(uv_pipe_t* channel, uv_process_t* process, const char* helper) { uv_process_options_t options; size_t exepath_size; char exepath[1024]; char* args[3]; int r; uv_stdio_container_t stdio[1]; r = uv_pipe_init(uv_default_loop(), channel, 1); ASSERT(r == 0); ASSERT(channel->ipc); exepath_size = sizeof(exepath); r = uv_exepath(exepath, &exepath_size); ASSERT(r == 0); exepath[exepath_size] = '\0'; args[0] = exepath; args[1] = (char*)helper; args[2] = NULL; memset(&options, 0, sizeof(options)); options.file = exepath; options.args = args; options.exit_cb = exit_cb; options.stdio = stdio; options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE; options.stdio[0].data.stream = (uv_stream_t*)channel; options.stdio_count = 1; r = uv_spawn(uv_default_loop(), process, options); ASSERT(r == 0); }
/// Sets the underlying file descriptor that will be read from. Only pipes /// and regular files are supported for now. /// /// @param rstream The `RStream` instance /// @param file The file descriptor void rstream_set_file(RStream *rstream, uv_file file) { rstream->file_type = uv_guess_handle(file); if (rstream->free_handle) { // If this is the second time we're calling this function, free the // previously allocated memory if (rstream->fread_idle != NULL) { uv_close((uv_handle_t *)rstream->fread_idle, close_cb); } else { uv_close((uv_handle_t *)rstream->stream, close_cb); } } if (rstream->file_type == UV_FILE) { // Non-blocking file reads are simulated with an idle handle that reads // in chunks of rstream->buffer_size, giving time for other events to // be processed between reads. rstream->fread_idle = xmalloc(sizeof(uv_idle_t)); uv_idle_init(uv_default_loop(), rstream->fread_idle); rstream->fread_idle->data = NULL; handle_set_rstream((uv_handle_t *)rstream->fread_idle, rstream); } else { // Only pipes are supported for now assert(rstream->file_type == UV_NAMED_PIPE || rstream->file_type == UV_TTY); rstream->stream = xmalloc(sizeof(uv_pipe_t)); uv_pipe_init(uv_default_loop(), (uv_pipe_t *)rstream->stream, 0); uv_pipe_open((uv_pipe_t *)rstream->stream, file); rstream->stream->data = NULL; handle_set_rstream((uv_handle_t *)rstream->stream, rstream); } rstream->fd = file; rstream->free_handle = true; }
static void on_connection(uv_stream_t* server, int status) { uv_stream_t* stream; int r; if (status != 0) { fprintf(stderr, "Connect error %d\n", uv_last_error().code); } ASSERT(status == 0); switch (serverType) { case TCP: stream = malloc(sizeof(uv_tcp_t)); ASSERT(stream != NULL); uv_tcp_init((uv_tcp_t*)stream); break; case PIPE: stream = malloc(sizeof(uv_pipe_t)); ASSERT(stream != NULL); uv_pipe_init((uv_pipe_t*)stream); break; default: ASSERT(0 && "Bad serverType"); abort(); } /* associate server with stream */ stream->data = server; r = uv_accept(server, stream); ASSERT(r == 0); r = uv_read_start(stream, echo_alloc, after_read); ASSERT(r == 0); }
void stdinReadStart(WrenVM* vm) { if (stdinStream == NULL) { if (uv_guess_handle(stdinDescriptor) == UV_TTY) { // stdin is connected to a terminal. uv_tty_t* handle = (uv_tty_t*)malloc(sizeof(uv_tty_t)); uv_tty_init(getLoop(), handle, stdinDescriptor, true); stdinStream = (uv_stream_t*)handle; } else { // stdin is a pipe or a file. uv_pipe_t* handle = (uv_pipe_t*)malloc(sizeof(uv_pipe_t)); uv_pipe_init(getLoop(), handle, false); uv_pipe_open(handle, stdinDescriptor); stdinStream = (uv_stream_t*)handle; } } uv_read_start(stdinStream, allocCallback, stdinReadCallback); // TODO: Check return. }
static void connection_cb(uv_handle_t* s, int status) { uv_stream_t* stream; int r; ASSERT(server == s); ASSERT(status == 0); if (type == TCP) { stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t)); uv_tcp_init((uv_tcp_t*)stream); } else { stream = (uv_stream_t*)malloc(sizeof(uv_pipe_t)); uv_pipe_init((uv_pipe_t*)stream); } r = uv_accept(s, stream); ASSERT(r == 0); r = uv_read_start(stream, buf_alloc, read_cb); ASSERT(r == 0); read_sockets++; max_read_sockets++; }
int main(void) { uv_loop_t loop; struct sockaddr_in addr; uv_connect_t connect_req; int fd, r; /* loop init */ uv_loop_init(&loop); #if USE_PIPE uv_pipe_init(&loop, &client, 1); uv_pipe_connect(&connect_req, &client, "/var/tmp/pipe.server1", connect_cb); #else /*tcp socket initial */ uv_ip4_addr("127.0.0.1", 4789, &addr); uv_tcp_init(&loop, &client); uv_tcp_connect(&connect_req, &client, (const struct sockaddr *)&addr, connect_cb); #endif r = uv_tty_init(&loop, &tty, 0, 1); printf("r=%d\n", r); uv_read_start((uv_stream_t *) & tty, alloc_cb, recv_cb); uv_run(&loop, UV_RUN_DEFAULT); printf("end\n"); return 0; }
LUALIB_API int luaopen_luv(lua_State *L) { #ifndef WIN32 signal(SIGPIPE, SIG_IGN); #endif int i; uv_loop_t* loop; luv_state_t* curr; luv_object_t* stdfh; lua_settop(L, 0); /* register decoders */ lua_pushcfunction(L, luvL_lib_decoder); lua_setfield(L, LUA_REGISTRYINDEX, "luv:lib:decoder"); #ifdef USE_ZMQ lua_pushcfunction(L, luvL_zmq_ctx_decoder); lua_setfield(L, LUA_REGISTRYINDEX, "luv:zmq:decoder"); #endif /* luv */ luvL_new_module(L, "luv", luv_funcs); /* luv.thread */ luvL_new_module(L, "luv_thread", luv_thread_funcs); lua_setfield(L, -2, "thread"); luvL_new_class(L, LUV_THREAD_T, luv_thread_meths); lua_pop(L, 1); if (!MAIN_INITIALIZED) { luvL_thread_init_main(L); lua_pop(L, 1); } /* luv.fiber */ luvL_new_module(L, "luv_fiber", luv_fiber_funcs); /* borrow coroutine.yield (fast on LJ2) */ lua_getglobal(L, "coroutine"); lua_getfield(L, -1, "yield"); lua_setfield(L, -3, "yield"); lua_pop(L, 1); /* coroutine */ lua_setfield(L, -2, "fiber"); luvL_new_class(L, LUV_FIBER_T, luv_fiber_meths); lua_pop(L, 1); /* luv.codec */ luvL_new_module(L, "luv_codec", luv_codec_funcs); lua_setfield(L, -2, "codec"); /* luv.timer */ luvL_new_module(L, "luv_timer", luv_timer_funcs); lua_setfield(L, -2, "timer"); luvL_new_class(L, LUV_TIMER_T, luv_timer_meths); lua_pop(L, 1); /* luv.idle */ luvL_new_module(L, "luv_idle", luv_idle_funcs); lua_setfield(L, -2, "idle"); luvL_new_class(L, LUV_IDLE_T, luv_idle_meths); lua_pop(L, 1); /* luv.fs */ luvL_new_module(L, "luv_fs", luv_fs_funcs); lua_setfield(L, -2, "fs"); luvL_new_class(L, LUV_FILE_T, luv_file_meths); lua_pop(L, 1); /* luv.pipe */ luvL_new_module(L, "luv_pipe", luv_pipe_funcs); lua_setfield(L, -2, "pipe"); luvL_new_class(L, LUV_PIPE_T, luv_stream_meths); luaL_register(L, NULL, luv_pipe_meths); lua_pop(L, 1); /* luv.std{in,out,err} */ if (!MAIN_INITIALIZED) { MAIN_INITIALIZED = 1; loop = luvL_event_loop(L); curr = luvL_state_self(L); const char* stdfhs[] = { "stdin", "stdout", "stderr" }; for (i = 0; i < 3; i++) { #ifdef WIN32 const uv_file fh = GetStdHandle(i == 0 ? STD_INPUT_HANDLE : (i == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE)); #else const uv_file fh = i; #endif stdfh = (luv_object_t*)lua_newuserdata(L, sizeof(luv_object_t)); luaL_getmetatable(L, LUV_PIPE_T); lua_setmetatable(L, -2); luvL_object_init(curr, stdfh); uv_pipe_init(loop, &stdfh->h.pipe, 0); uv_pipe_open(&stdfh->h.pipe, fh); lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, stdfhs[i]); lua_setfield(L, -2, stdfhs[i]); } } /* luv.net */ luvL_new_module(L, "luv_net", luv_net_funcs); lua_setfield(L, -2, "net"); luvL_new_class(L, LUV_NET_TCP_T, luv_stream_meths); luaL_register(L, NULL, luv_net_tcp_meths); lua_pop(L, 1); /* luv.process */ luvL_new_module(L, "luv_process", luv_process_funcs); lua_setfield(L, -2, "process"); luvL_new_class(L, LUV_PROCESS_T, luv_process_meths); lua_pop(L, 1); /* luv.zmq */ #ifdef USE_ZMQ luvL_new_module(L, "luv_zmq", luv_zmq_funcs); const luv_const_reg_t* c = luv_zmq_consts; for (; c->key; c++) { lua_pushinteger(L, c->val); lua_setfield(L, -2, c->key); } lua_setfield(L, -2, "zmq"); luvL_new_class(L, LUV_ZMQ_CTX_T, luv_zmq_ctx_meths); luvL_new_class(L, LUV_ZMQ_SOCKET_T, luv_zmq_socket_meths); lua_pop(L, 2); #endif lua_settop(L, 1); return 1; }
void spawn() { int i; char** env = NULL; env = env_copy(environ, env); child = malloc(sizeof(uv_process_t)); uv_stdio_container_t stdio[4]; uv_process_options_t options; uv_pipe_init(loop, &child_stdout, 0); uv_pipe_init(loop, &child_stderr, 0); uv_pipe_init(loop, &child_ipc, 0); // // Setup child's stdio. stdout and stderr are pipes so that we can read // child process' output. // FD 3 is a pipe used for IPC. // options.stdio_count = 4; stdio[0].flags = UV_INHERIT_FD; stdio[0].data.fd = 0; stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; stdio[1].data.stream = (uv_stream_t*) &child_stdout; stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; stdio[2].data.stream = (uv_stream_t*) &child_stderr; stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; stdio[3].data.stream = (uv_stream_t*) &child_ipc; options.env = env; options.cwd = NULL; options.file = arguments[0]; options.args = arguments; options.flags = 0; options.stdio = stdio; options.exit_cb = on_process_exit; for (i = 0; i < PLUGIN_COUNT; i++) { if (plugins[i].process_options_cb) { plugins[i].process_options_cb(&options); } } if (uv_spawn(loop, child, options)) { fprintf(stderr, "uv_spawn: %s\n", uv_err_name(uv_last_error(loop))); return; } for (i = 0; i < PLUGIN_COUNT; i++) { if (plugins[i].process_spawned_cb) { plugins[i].process_spawned_cb(child, &options); } } uv_read_start(options.stdio[1].data.stream, forza__on_alloc, forza__on_stdout_read); uv_read_start(options.stdio[2].data.stream, forza__on_alloc, forza__on_stderr_read); uv_read_start(options.stdio[3].data.stream, forza__on_alloc, forza__on_ipc_read); // Switch to using `options->env` here instead of `env`, since plugins can // override `options->env` using, for example `env_set`, like in the start // plugin. env_free(options.env); }
static int stdio_over_pipes_helper() { /* Write several buffers to test that the write order is preserved. */ char* buffers[] = { "he", "ll", "o ", "wo", "rl", "d", "\n" }; uv_write_t write_req[ARRAY_SIZE(buffers)]; uv_buf_t buf[ARRAY_SIZE(buffers)]; int r, i; uv_loop_t* loop = uv_default_loop(); ASSERT(UV_NAMED_PIPE == uv_guess_handle(0)); ASSERT(UV_NAMED_PIPE == uv_guess_handle(1)); r = uv_pipe_init(loop, &stdin_pipe, 0); ASSERT(r == 0); r = uv_pipe_init(loop, &stdout_pipe, 0); ASSERT(r == 0); uv_pipe_open(&stdin_pipe, 0); uv_pipe_open(&stdout_pipe, 1); /* Unref both stdio handles to make sure that all writes complete. */ uv_unref(loop); uv_unref(loop); for (i = 0; i < ARRAY_SIZE(buffers); i++) { buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i])); } for (i = 0; i < ARRAY_SIZE(buffers); i++) { r = uv_write(&write_req[i], (uv_stream_t*)&stdout_pipe, &buf[i], 1, after_pipe_write); ASSERT(r == 0); } uv_run(loop); ASSERT(after_write_called == 7); ASSERT(on_pipe_read_called == 0); ASSERT(close_cb_called == 0); uv_ref(loop); uv_ref(loop); r = uv_read_start((uv_stream_t*)&stdin_pipe, on_pipe_read_alloc, on_pipe_read); ASSERT(r == 0); uv_run(loop); ASSERT(after_write_called == 7); ASSERT(on_pipe_read_called == 1); ASSERT(close_cb_called == 2); return 0; }
/* u2_term_io_init(): initialize terminal. */ void u2_term_io_init() { u2_utty* uty_u = malloc(sizeof(u2_utty)); if ( u2_yes == u2_Host.ops_u.dem ) { uty_u->fid_i = 1; uv_pipe_init(u2L, &(uty_u->pop_u), uty_u->fid_i); uv_pipe_open(&(uty_u->pop_u), uty_u->fid_i); } else { // Initialize event processing. Rawdog it. // { uty_u->fid_i = 0; // stdin, yes we write to it... uv_poll_init(u2L, &(uty_u->wax_u), uty_u->fid_i); uv_poll_start(&(uty_u->wax_u), UV_READABLE | UV_WRITABLE, _term_poll_cb); } // Configure horrible stateful terminfo api. // { if ( 0 != setupterm(0, 2, 0) ) { c3_assert(!"init-setupterm"); } } // Load terminfo strings. // { c3_w len_w; # define _utfo(way, nam) \ { \ uty_u->ufo_u.way.nam##_y = (const c3_y *) tigetstr(#nam); \ c3_assert(uty_u->ufo_u.way.nam##_y); \ } uty_u->ufo_u.inn.max_w = 0; #if 1 _utfo(inn, kcuu1); _utfo(inn, kcud1); _utfo(inn, kcub1); _utfo(inn, kcuf1); _utfo(out, clear); _utfo(out, el); // _utfo(out, el1); _utfo(out, ed); _utfo(out, bel); _utfo(out, cub1); _utfo(out, cuf1); _utfo(out, cuu1); _utfo(out, cud1); // _utfo(out, cub); // _utfo(out, cuf); #else // libuv hardcodes an ansi terminal - which doesn't seem to work... // uty_u->ufo_u.out.clear_y = "\033[H\033[J"; uty_u->ufo_u.out.el_y = "\033[K"; uty_u->ufo_u.out.ed_y = "\033[J"; uty_u->ufo_u.out.bel_y = "\007"; uty_u->ufo_u.out.cub1_y = "\010"; uty_u->ufo_u.out.cud1_y = "\033[B"; uty_u->ufo_u.out.cuu1_y = "\033[A"; uty_u->ufo_u.out.cuf1_y = "\033[C"; #endif // Terminfo chronically reports the wrong sequence for arrow // keys on xterms. Drastic fix for ridiculous unacceptable bug. // Yes, we could fix this with smkx/rmkx, but this is retarded as well. { uty_u->ufo_u.inn.kcuu1_y = (const c3_y*)"\033[A"; uty_u->ufo_u.inn.kcud1_y = (const c3_y*)"\033[B"; uty_u->ufo_u.inn.kcuf1_y = (const c3_y*)"\033[C"; uty_u->ufo_u.inn.kcub1_y = (const c3_y*)"\033[D"; } uty_u->ufo_u.inn.max_w = 0; if ( (len_w = strlen((c3_c*)uty_u->ufo_u.inn.kcuu1_y)) > uty_u->ufo_u.inn.max_w ) { uty_u->ufo_u.inn.max_w = len_w; } if ( (len_w = strlen((c3_c*)uty_u->ufo_u.inn.kcud1_y)) > uty_u->ufo_u.inn.max_w ) { uty_u->ufo_u.inn.max_w = len_w; } if ( (len_w = strlen((c3_c*)uty_u->ufo_u.inn.kcub1_y)) > uty_u->ufo_u.inn.max_w ) { uty_u->ufo_u.inn.max_w = len_w; } if ( (len_w = strlen((c3_c*)uty_u->ufo_u.inn.kcuf1_y)) > uty_u->ufo_u.inn.max_w ) { uty_u->ufo_u.inn.max_w = len_w; } } // Load old terminal state to restore. // #if 1 { if ( 0 != tcgetattr(uty_u->fid_i, &uty_u->bak_u) ) { c3_assert(!"init-tcgetattr"); } if ( -1 == fcntl(uty_u->fid_i, F_GETFL, &uty_u->cug_i) ) { c3_assert(!"init-fcntl"); } uty_u->cug_i &= ~O_NONBLOCK; // could fix? uty_u->nob_i = uty_u->cug_i | O_NONBLOCK; // O_NDELAY on older unix } // Construct raw termios configuration. // { uty_u->raw_u = uty_u->bak_u; uty_u->raw_u.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN); uty_u->raw_u.c_iflag &= ~(ICRNL | INPCK | ISTRIP); uty_u->raw_u.c_cflag &= ~(CSIZE | PARENB); uty_u->raw_u.c_cflag |= CS8; uty_u->raw_u.c_oflag &= ~(OPOST); uty_u->raw_u.c_cc[VMIN] = 0; uty_u->raw_u.c_cc[VTIME] = 0; } #endif // Initialize mirror and accumulator state. // { uty_u->tat_u.mir.lin_w = 0; uty_u->tat_u.mir.len_w = 0; uty_u->tat_u.mir.cus_w = 0; uty_u->tat_u.esc.ape = u2_no; uty_u->tat_u.esc.bra = u2_no; uty_u->tat_u.fut.len_w = 0; uty_u->tat_u.fut.wid_w = 0; } } // This is terminal 1, linked in host. // { uty_u->tid_l = 1; uty_u->out_u = 0; uty_u->tou_u = 0; uty_u->nex_u = u2_Host.uty_u; u2_Host.uty_u = uty_u; u2_Host.tem_u = uty_u; } if ( u2_no == u2_Host.ops_u.dem ) { // Start raw input. // { if ( 0 != tcsetattr(uty_u->fid_i, TCSADRAIN, &uty_u->raw_u) ) { c3_assert(!"init-tcsetattr"); } if ( -1 == fcntl(uty_u->fid_i, F_SETFL, uty_u->nob_i) ) { c3_assert(!"init-fcntl"); } } } }
Pipe(const bool fd_pass = false): stream() { uv_pipe_init(uv_default_loop(), get(), fd_pass ? 1 : 0); }
Pipe(loop& l, const bool fd_pass = false): stream() { uv_pipe_init(l.get(), get(), fd_pass ? 1 : 0); }
extern "C" int rust_uv_pipe_init(uv_loop_t *loop, uv_pipe_t* p, int ipc) { return uv_pipe_init(loop, p, ipc); }
bud_error_t bud_worker(bud_config_t* config) { int r; bud_error_t err; bud_log(config, kBudLogDebug, "worker starting"); config->loop = uv_default_loop(); config->ipc = malloc(sizeof(*config->ipc)); config->signal.sighup = malloc(sizeof(*config->signal.sighup)); if (config->ipc == NULL || config->signal.sighup == NULL) { err = bud_error_str(kBudErrNoMem, "config->ipc"); goto fatal; } config->ipc->data = config; config->signal.sighup->data = config; r = uv_pipe_init(config->loop, config->ipc, 1); if (r != 0) { err = bud_error_num(kBudErrIPCPipeInit, r); goto fatal; } r = uv_pipe_open(config->ipc, 0); if (r != 0) { err = bud_error_num(kBudErrIPCPipeOpen, r); goto failed_pipe_open; } r = uv_read_start((uv_stream_t*) config->ipc, bud_worker_alloc_cb, bud_worker_read_cb); if (r != 0) { err = bud_error_num(kBudErrIPCReadStart, r); goto failed_pipe_open; } #ifndef _WIN32 /* Drop privileges */ err = bud_config_drop_privileges(config); if (!bud_is_ok(err)) goto failed_pipe_open; r = uv_signal_init(config->loop, config->signal.sighup); if (r != 0) { err = bud_error_num(kBudErrSignalInit, r); goto failed_pipe_open; } r = uv_signal_start(config->signal.sighup, bud_worker_signal_cb, SIGHUP); if (r != 0) { err = bud_error_num(kBudErrSignalInit, r); goto failed_signal_start; } #endif /* !_WIN32 */ err = bud_ok(); return err; #ifndef _WIN32 failed_signal_start: uv_close((uv_handle_t*) config->signal.sighup, bud_worker_close_cb); #endif /* !_WIN32 */ failed_pipe_open: uv_close((uv_handle_t*) config->ipc, bud_worker_close_cb); goto cleanup; fatal: free(config->ipc); cleanup: config->ipc = NULL; return err; }
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); }
int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) { uv_stdio_container_t proc_stdio[3]; uv_process_options_t proc_opts; uv_process_t proc; uv_pipe_t proc_stdin, proc_stdout; uv_write_t write_req; int expected_exits = 1; ProcessData pdata = { .reading = false, .exited = 0, .old_mode = cur_tmode, .old_state = State, .shell_stdin = (uv_stream_t *)&proc_stdin, .wbuffer = NULL, }; out_flush(); if (opts & kShellOptCooked) { // set to normal mode settmode(TMODE_COOK); } // While the child is running, ignore terminating signals signal_reject_deadly(); // Create argv for `uv_spawn` // TODO(tarruda): we can use a static buffer for small argument vectors. 1024 // bytes should be enough for most of the commands and if more is necessary // we can allocate a another buffer proc_opts.args = shell_build_argv(cmd, extra_shell_arg); proc_opts.file = proc_opts.args[0]; proc_opts.exit_cb = exit_cb; // Initialize libuv structures proc_opts.stdio = proc_stdio; proc_opts.stdio_count = 3; // Hide window on Windows :) proc_opts.flags = UV_PROCESS_WINDOWS_HIDE; proc_opts.cwd = NULL; proc_opts.env = NULL; // The default is to inherit all standard file descriptors(this will change // when the UI is moved to an external process) proc_stdio[0].flags = UV_INHERIT_FD; proc_stdio[0].data.fd = 0; proc_stdio[1].flags = UV_INHERIT_FD; proc_stdio[1].data.fd = 1; proc_stdio[2].flags = UV_INHERIT_FD; proc_stdio[2].data.fd = 2; if (opts & (kShellOptHideMess | kShellOptExpand)) { // Ignore the shell stdio(redirects to /dev/null on unixes) proc_stdio[0].flags = UV_IGNORE; proc_stdio[1].flags = UV_IGNORE; proc_stdio[2].flags = UV_IGNORE; } else { State = EXTERNCMD; if (opts & kShellOptWrite) { // Write from the current buffer into the process stdin uv_pipe_init(uv_default_loop(), &proc_stdin, 0); write_req.data = &pdata; proc_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; proc_stdio[0].data.stream = (uv_stream_t *)&proc_stdin; } if (opts & kShellOptRead) { // Read from the process stdout into the current buffer uv_pipe_init(uv_default_loop(), &proc_stdout, 0); proc_stdout.data = &pdata; proc_stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; proc_stdio[1].data.stream = (uv_stream_t *)&proc_stdout; ga_init(&pdata.ga, 1, BUFFER_LENGTH); } } if (uv_spawn(uv_default_loop(), &proc, &proc_opts)) { // Failed, probably due to `sh` not being executable if (!emsg_silent) { MSG_PUTS(_("\nCannot execute shell ")); msg_outtrans(p_sh); msg_putchar('\n'); } return proc_cleanup_exit(&pdata, &proc_opts, opts); } // Assign the flag address after `proc` is initialized by `uv_spawn` proc.data = &pdata; if (opts & kShellOptWrite) { // Queue everything for writing to the shell stdin write_selection(&write_req); expected_exits++; } if (opts & kShellOptRead) { // Start the read stream for the shell stdout uv_read_start((uv_stream_t *)&proc_stdout, alloc_cb, read_cb); expected_exits++; } // Keep running the loop until all three handles are completely closed while (pdata.exited < expected_exits) { uv_run(uv_default_loop(), UV_RUN_ONCE); if (got_int) { // Forward SIGINT to the shell // TODO(tarruda): for now this is only needed if the terminal is in raw // mode, but when the UI is externalized we'll also need it, so leave it // here uv_process_kill(&proc, SIGINT); got_int = false; } } if (opts & kShellOptRead) { if (pdata.ga.ga_len > 0) { // If there's an unfinished line in the growable array, append it now. append_ga_line(&pdata.ga); // remember that the NL was missing curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; } else { curbuf->b_no_eol_lnum = 0; } ga_clear(&pdata.ga); } if (opts & kShellOptWrite) { free(pdata.wbuffer); } return proc_cleanup_exit(&pdata, &proc_opts, opts); } static int tokenize(char_u *str, char **argv) { int argc = 0, len; char_u *p = str; while (*p != NUL) { len = word_length(p); if (argv != NULL) { // Fill the slot argv[argc] = xmalloc(len + 1); memcpy(argv[argc], p, len); argv[argc][len] = NUL; } argc++; p += len; p = skipwhite(p); } return argc; }
static bool caerOutputUnixSocketServerInit(caerModuleData moduleData) { // First, always create all needed setting nodes, set their default values // and add their listeners. sshsNodeCreateString(moduleData->moduleNode, "socketPath", "/tmp/caer.sock", 2, PATH_MAX, SSHS_FLAGS_NORMAL, "Unix Socket path for writing output data (server mode, create new socket)."); sshsNodeCreateInt( moduleData->moduleNode, "backlogSize", 5, 1, 32, SSHS_FLAGS_NORMAL, "Maximum number of pending connections."); sshsNodeCreateInt(moduleData->moduleNode, "concurrentConnections", 10, 1, 128, SSHS_FLAGS_NORMAL, "Maximum number of concurrent active connections."); // Allocate memory. size_t numClients = (size_t) sshsNodeGetInt(moduleData->moduleNode, "concurrentConnections"); outputCommonNetIO streams = malloc(sizeof(*streams) + (numClients * sizeof(uv_stream_t *))); if (streams == NULL) { caerModuleLog(moduleData, CAER_LOG_ERROR, "Failed to allocate memory for streams structure."); return (false); } streams->server = malloc(sizeof(uv_pipe_t)); if (streams->server == NULL) { free(streams); caerModuleLog(moduleData, CAER_LOG_ERROR, "Failed to allocate memory for network server."); return (false); } // Initialize common info. streams->isTCP = false; streams->isUDP = false; streams->isPipe = true; streams->activeClients = 0; streams->clientsSize = numClients; for (size_t i = 0; i < streams->clientsSize; i++) { streams->clients[i] = NULL; } // Remember address. streams->address = sshsNodeGetString(moduleData->moduleNode, "socketPath"); streams->server->data = streams; // Initialize loop and network handles. int retVal = uv_loop_init(&streams->loop); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_loop_init", free(streams->server); free(streams->address); free(streams); return (false)); retVal = uv_pipe_init(&streams->loop, (uv_pipe_t *) streams->server, false); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_pipe_init", uv_loop_close(&streams->loop); free(streams->server); free(streams->address); free(streams); return (false)); retVal = uv_pipe_bind((uv_pipe_t *) streams->server, streams->address); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_pipe_bind", libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false)); retVal = uv_listen( streams->server, sshsNodeGetInt(moduleData->moduleNode, "backlogSize"), &caerOutputCommonOnServerConnection); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_listen", libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false)); // Start. if (!caerOutputCommonInit(moduleData, -1, streams)) { libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false); } return (true); }
void *init_stdio_handle(uv_file fd,int readable) { void *handle; uv_handle_type type = uv_guess_handle(fd); jl_uv_file_t *file; #ifndef _OS_WINDOWS_ // Duplicate the file descritor so we can later dup it over if we want to redirect // STDIO without having to worry about closing the associated libuv object. // On windows however, libuv objects remember streams by their HANDLE, so this is // unnessecary. fd = dup(fd); #endif //printf("%d: %d -- %d\n", fd, type); switch(type) { case UV_TTY: handle = malloc(sizeof(uv_tty_t)); if (uv_tty_init(jl_io_loop,(uv_tty_t*)handle,fd,readable)) { jl_errorf("Error initializing stdio in uv_tty_init (%d, %d)\n", fd, type); abort(); } ((uv_tty_t*)handle)->data=0; uv_tty_set_mode((void*)handle,0); //cooked stdio break; case UV_FILE: file = malloc(sizeof(jl_uv_file_t)); file->loop = jl_io_loop; file->type = UV_FILE; file->file = fd; file->data = 0; handle = file; break; case UV_NAMED_PIPE: handle = malloc(sizeof(uv_pipe_t)); if (uv_pipe_init(jl_io_loop, (uv_pipe_t*)handle, (readable?UV_PIPE_READABLE:UV_PIPE_WRITABLE))) { jl_errorf("Error initializing stdio in uv_pipe_init (%d, %d)\n", fd, type); abort(); } if (uv_pipe_open((uv_pipe_t*)handle,fd)) { jl_errorf("Error initializing stdio in uv_pipe_open (%d, %d)\n", fd, type); abort(); } ((uv_pipe_t*)handle)->data=0; break; case UV_TCP: handle = malloc(sizeof(uv_tcp_t)); if (uv_tcp_init(jl_io_loop, (uv_tcp_t*)handle)) { jl_errorf("Error initializing stdio in uv_tcp_init (%d, %d)\n", fd, type); abort(); } if (uv_tcp_open((uv_tcp_t*)handle,fd)) { jl_errorf("Error initializing stdio in uv_tcp_open (%d, %d)\n", fd, type); abort(); } ((uv_tcp_t*)handle)->data=0; break; case UV_UDP: default: jl_errorf("This type of handle for stdio is not yet supported (%d, %d)!\n", fd, type); handle = NULL; break; } return handle; }
int job_start(char **argv, void *data, rstream_cb stdout_cb, rstream_cb stderr_cb, job_exit_cb job_exit_cb) { int i; Job *job; // Search for a free slot in the table for (i = 0; i < MAX_RUNNING_JOBS; i++) { if (table[i] == NULL) { break; } } if (i == MAX_RUNNING_JOBS) { // No free slots return 0; } job = xmalloc(sizeof(Job)); // Initialize job->id = i + 1; job->pending_refs = 3; job->pending_closes = 4; job->data = data; job->stdout_cb = stdout_cb; job->stderr_cb = stderr_cb; job->exit_cb = job_exit_cb; job->stopped = false; job->exit_timeout = EXIT_TIMEOUT; job->proc_opts.file = argv[0]; job->proc_opts.args = argv; job->proc_opts.stdio = job->stdio; job->proc_opts.stdio_count = 3; job->proc_opts.flags = UV_PROCESS_WINDOWS_HIDE; job->proc_opts.exit_cb = exit_cb; job->proc_opts.cwd = NULL; job->proc_opts.env = NULL; job->proc.data = NULL; job->proc_stdin.data = NULL; job->proc_stdout.data = NULL; job->proc_stderr.data = NULL; // Initialize the job std{in,out,err} uv_pipe_init(uv_default_loop(), &job->proc_stdin, 0); job->stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; job->stdio[0].data.stream = (uv_stream_t *)&job->proc_stdin; uv_pipe_init(uv_default_loop(), &job->proc_stdout, 0); job->stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[1].data.stream = (uv_stream_t *)&job->proc_stdout; uv_pipe_init(uv_default_loop(), &job->proc_stderr, 0); job->stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; job->stdio[2].data.stream = (uv_stream_t *)&job->proc_stderr; // Spawn the job if (uv_spawn(uv_default_loop(), &job->proc, &job->proc_opts) != 0) { free_job(job); return -1; } // Give all handles a reference to the job handle_set_job((uv_handle_t *)&job->proc, job); handle_set_job((uv_handle_t *)&job->proc_stdin, job); handle_set_job((uv_handle_t *)&job->proc_stdout, job); handle_set_job((uv_handle_t *)&job->proc_stderr, job); job->in = wstream_new(JOB_WRITE_MAXMEM); wstream_set_stream(job->in, (uv_stream_t *)&job->proc_stdin); // Start the readable streams job->out = rstream_new(read_cb, JOB_BUFFER_SIZE, job, true); job->err = rstream_new(read_cb, JOB_BUFFER_SIZE, job, true); rstream_set_stream(job->out, (uv_stream_t *)&job->proc_stdout); rstream_set_stream(job->err, (uv_stream_t *)&job->proc_stderr); rstream_start(job->out); rstream_start(job->err); // Save the job to the table table[i] = job; // Start polling job status if this is the first if (job_count == 0) { uv_prepare_start(&job_prepare, job_prepare_cb); } job_count++; return job->id; }
int ftw_libuv_spawn_process(struct ftw_libuv_callsite **callsite, LVUserEventRef *lv_event, char *exe, char *cmd, int64_t *exit_code, int64_t *signal) { int rc; char *args [3]; uv_loop_t loop; uv_pipe_t stdout_pipe; uv_pipe_t stderr_pipe; uv_process_t new_process; uv_process_options_t opts = {0}; uv_stdio_container_t iostreams [3]; struct ftw_libuv_process proc_data = {0}; struct ftw_libuv_stream context; /* Preconditions expected of LabVIEW. */ ftw_assert(callsite && *callsite && lv_event && cmd); rc = uv_loop_init(&loop); if (rc) { return rc; } args[0] = exe; args[1] = cmd; args[2] = NULL; proc_data.exit_code = exit_code; proc_data.signal = signal; new_process.data = &proc_data; context.msg_to_lv_event = lv_event; stdout_pipe.data = &context; stderr_pipe.data = &context; rc = uv_pipe_init(&loop, &stdout_pipe, 0); if (rc) { uv_loop_close(&loop); return rc; } rc = uv_pipe_init(&loop, &stderr_pipe, 0); if (rc) { uv_loop_close(&loop); return rc; } opts.stdio_count = 3; opts.stdio = iostreams; opts.stdio[0].flags = UV_IGNORE; opts.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; opts.stdio[1].data.stream = (uv_stream_t *) &stdout_pipe; opts.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; opts.stdio[2].data.stream = (uv_stream_t *) &stderr_pipe; //opts.stdio[2].flags = UV_IGNORE; opts.file = exe; opts.args = args; opts.exit_cb = ftw_libuv_callback_process_exit; rc = uv_spawn(&loop, &new_process, &opts); if (rc) { uv_loop_close(&loop); return rc; } rc = uv_read_start((uv_stream_t*) &stdout_pipe, ftw_libuv_callback_alloc, ftw_libuv_callback_read_pipe); if (rc) { uv_loop_close(&loop); return rc; } rc = uv_read_start((uv_stream_t*) &stderr_pipe, ftw_libuv_callback_alloc, ftw_libuv_callback_read_pipe); if (rc) { uv_loop_close(&loop); return rc; } rc = uv_run(&loop, UV_RUN_DEFAULT); if (rc) { uv_loop_close(&loop); return rc; } rc = uv_loop_close(&loop); return rc; }
static PyObject * Pipe_func_write2(Pipe *self, PyObject *args) { uv_buf_t buf; Py_buffer *view; PyObject *callback, *send_handle; callback = Py_None; RAISE_IF_HANDLE_NOT_INITIALIZED(self, NULL); RAISE_IF_HANDLE_CLOSED(self, PyExc_HandleClosedError, NULL); view = PyMem_Malloc(sizeof *view); if (!view) { PyErr_NoMemory(); return NULL; } #ifdef PYUV_PYTHON3 if (!PyArg_ParseTuple(args, "y*O|O:write", view, &send_handle, &callback)) { #else if (!PyArg_ParseTuple(args, "s*O|O:write", view, &send_handle, &callback)) { #endif return NULL; } if (PyObject_IsSubclass((PyObject *)send_handle->ob_type, (PyObject *)&StreamType)) { if (UV_HANDLE(send_handle)->type != UV_TCP && UV_HANDLE(send_handle)->type != UV_NAMED_PIPE) { PyErr_SetString(PyExc_TypeError, "Only TCP and Pipe objects are supported for write2"); goto error; } } else if (PyObject_IsSubclass((PyObject *)send_handle->ob_type, (PyObject *)&UDPType)) { /* empty */ } else { PyErr_SetString(PyExc_TypeError, "Only Stream and UDP objects are supported"); goto error; } if (callback != Py_None && !PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "a callable or None is required"); goto error; } buf = uv_buf_init(view->buf, view->len); return pyuv_stream_write((Stream *)self, view, &buf, 1, callback, send_handle); error: PyBuffer_Release(view); PyMem_Free(view); return NULL; } static int Pipe_tp_init(Pipe *self, PyObject *args, PyObject *kwargs) { int r; Loop *loop; PyObject *ipc = Py_False; UNUSED_ARG(kwargs); RAISE_IF_HANDLE_INITIALIZED(self, -1); if (!PyArg_ParseTuple(args, "O!|O!:__init__", &LoopType, &loop, &PyBool_Type, &ipc)) { return -1; } r = uv_pipe_init(loop->uv_loop, (uv_pipe_t *)UV_HANDLE(self), (ipc == Py_True) ? 1 : 0); if (r != 0) { RAISE_UV_EXCEPTION(loop->uv_loop, PyExc_PipeError); return -1; } initialize_handle(HANDLE(self), loop); return 0; }
void ::yajr::comms::internal::ActiveUnixPeer::retry() { if (destroying_) { LOG(INFO) << this << "Not retrying because of pending destroy" ; return; } if (uvRefCnt_ != 1) { LOG(INFO) << this << " has to wait for reference count to fall to 1 before retrying" ; insert(internal::Peer::LoopData::RETRY_TO_CONNECT); return; } int rc; if ((rc = uv_pipe_init( getUvLoop(), reinterpret_cast<uv_pipe_t *>(getHandle()), 0))) { LOG(WARNING) << "uv_pipe_init: [" << uv_err_name(rc) << "] " << uv_strerror(rc) ; onError(rc); insert(internal::Peer::LoopData::RETRY_TO_CONNECT); return; } /* potentially switch uv loop if some rebalancing is needed */ uv_loop_t * newLoop = uvLoopSelector_(getData()); if (newLoop != getHandle()->loop) { getLoopData()->down(); getHandle()->loop = newLoop; getLoopData()->up(); } /* uv_pipe_connect errors are always asynchronous */ uv_pipe_connect(&connect_req_, reinterpret_cast<uv_pipe_t *>(getHandle()), socketName_.c_str(), on_active_connection); /* workaround for libuv synchronous uv_pipe_connect() failures bug */ getLoopData()->kickLibuv(); up(); status_ = Peer::kPS_CONNECTING; insert(internal::Peer::LoopData::ATTEMPTING_TO_CONNECT); VLOG(1) << this << " issued a pipe connect request: " << socketName_ ; }
void SysProcess::invoke() { int r; char** args = NULL; //if ( this->directory_ == nullptr ) //{ // char path[512] = { 0 }; // getcwd( path , 512 ); // int path_len = strlen( path ); // this->directory_ = new char[path_len + 1]; // memset( this->directory_ , 0 , path_len + 1 ); // memcpy( this->directory_ , path , strlen( path ) ); //} printf( "File:%s\r\n" , this->file_ ); if ( args_ == nullptr ) { //char path[512] = { 0 }; //getcwd( path , 512 ); //args = new char*[2]; //args[0] = ' '; //args[1] = NULL; //args[0] = new char[strlen( path ) + 1]; //memset( args[0] , 0 , strlen( path ) + 1 ); //memcpy( args[0] , path , strlen( path ) ); //args[1] = NULL; } else { args = new char*[64]; for ( size_t i = 0; i < 64; i++ ) { args[i] = new char[512]; memset( args[i] , 0 , 512 ); args[i][0] = ' '; } auto raw_args = this->args_; size_t len = strlen( this->args_ ); int start_pos = 0; #ifdef _WIN32 int row = 0; #else int row = 0; #endif int col = 0; bool has_dot = false; for ( int e = start_pos; e < len; e++ ) { if ( raw_args[e] == '\'') { if ( has_dot ) has_dot = false; else has_dot = true; } if ( raw_args[e] == ' ' && !has_dot) { printf( "Args:%s\r\n", args[row] ); col = 0; row++; args[row][col] = ' '; col = 1; } else { args[row][col] = raw_args[e]; col++; } } printf( "Args:%s\r\n" , args[row] ); args[row+1] = NULL; } auto loop = uv_default_loop(); this->pipe_ = { 0 }; r = uv_pipe_init( loop , &this->pipe_ , 0 ); this->pipe_.data = this; this->options.exit_cb = SysProcess::uv_process_exit_callback; this->options.file = this->file_; this->options.args = args; this->options.cwd = this->directory_; this->child_req.data = this; this->options.stdio_count = 3; uv_stdio_container_t child_stdio[3]; // ( uv_stdio_flags )( UV_CREATE_PIPE | UV_READABLE_PIPE ); child_stdio[0].flags = UV_IGNORE; child_stdio[1].flags = ( uv_stdio_flags )( UV_CREATE_PIPE | UV_WRITABLE_PIPE ); child_stdio[1].data.stream = ( uv_stream_t* )&this->pipe_; child_stdio[2].flags = UV_IGNORE; this->options.stdio = child_stdio; r = uv_spawn( loop , &this->child_req , &this->options ); if ( r != 0 ) { printf( "uv_spawn: %s\r\n" , uv_strerror( r ) ); } r = uv_read_start( ( uv_stream_t* )&this->pipe_ , SysProcess::uv_process_alloc_buffer , SysProcess::uv_prcoess_read_stream ); if ( r != 0 ) { printf( "uv_read_start: %s\r\n" , uv_strerror( r ) ); } delete[] args; }