static void channel_close_listener(Channel * c) { LINK * l = NULL; for (l = terms_list.next; l != &terms_list;) { Terminal * term = link2term(l); l = l->next; if (term->channel == c && !term->terminated) { trace(LOG_ALWAYS, "Terminal is left launched: %s", tid2id(get_process_pid(term->prs))); kill_term(term); } } }
static void send_event_terminal_exited(OutputStream * out, Terminal * term) { write_stringz(out, "E"); write_stringz(out, TERMINALS); write_stringz(out, "exited"); json_write_string(out, tid2id(get_process_pid(term->prs))); write_stream(out, 0); json_write_ulong(out, get_process_exit_code(term->prs)); write_stream(out, 0); write_stream(out, MARKER_EOM); }
int handle_dollar(t_expander *exp) { char *s; s = exp->tmp + 1; if (!*s) return (append(exp)); else if (*s == '?') return (get_exit_status(exp)); else if (*s == '$') return (get_process_pid(exp)); else if (*s == '0') return (get_shell_name(exp)); else return (get_env_variable(exp, s)); }
static int kill_term(Terminal * term) { int err = 0; int pid = get_process_pid(term->prs); #if defined(_WIN32) || defined(__CYGWIN__) HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (h == NULL) { err = set_win32_errno(GetLastError()); } else { if (!TerminateProcess(h, 1)) err = set_win32_errno(GetLastError()); if (!CloseHandle(h) && !err) err = set_win32_errno(GetLastError()); } #else if (kill(pid, get_process_out_state(term->prs) ? TERM_EXIT_SIGNAL : SIGKILL) < 0) err = errno; #endif term->terminated = 1; return err; }
static void send_event_terminal_win_size_changed(OutputStream * out, Terminal * term) { unsigned ws_col = 0; unsigned ws_row = 0; get_process_tty_win_size(term->prs, &ws_col, &ws_row); write_stringz(out, "E"); write_stringz(out, TERMINALS); write_stringz(out, "winSizeChanged"); json_write_string(out, tid2id(get_process_pid(term->prs))); write_stream(out, 0); json_write_long(out, ws_col); write_stream(out, 0); json_write_long(out, ws_row); write_stream(out, 0); write_stream(out, MARKER_EOM); }
static void command_launch(char * token, Channel * c) { int err = 0; char encoding[TERM_PROP_DEF_SIZE]; char pty_type[TERM_PROP_DEF_SIZE]; const char * args[] = TERM_LAUNCH_ARGS; const char * exec = TERM_LAUNCH_EXEC; int selfattach = 0; ProcessStartParams prms; Terminal * term = (Terminal *)loc_alloc_zero(sizeof(Terminal)); memset(&prms, 0, sizeof(prms)); json_read_string(&c->inp, pty_type, sizeof(pty_type)); json_test_char(&c->inp, MARKER_EOA); json_read_string(&c->inp, encoding, sizeof(encoding)); json_test_char(&c->inp, MARKER_EOA); prms.envp = read_env(&c->inp); json_test_char(&c->inp, MARKER_EOM); #if !defined(_WIN32) && !defined(__CYGWIN__) { struct stat st; if (err == 0 && stat(exec, &st) != 0) { err = errno; if (err == ENOENT) { static char fnm[FILE_PATH_SIZE]; /* On some systems (e.g. Free DSB) bash is installed under /usr/local */ assert(exec[0] == '/'); snprintf(fnm, sizeof(fnm), "/usr/local%s", exec); if (stat(fnm, &st) == 0) { args[0] = exec = fnm; err = 0; } } if (err == ENOENT && strcmp(exec, "/bin/bash") == 0) { /* "bash" not found, try "sh" */ const char * fnm = "/bin/sh"; if (stat(fnm, &st) == 0) { args[0] = exec = fnm; err = 0; } } if (err) err = set_fmt_errno(err, "Cannot start %s", exec); } } set_terminal_env(&prms.envp, pty_type, encoding, exec); prms.dir = getenv("HOME"); if (prms.dir) prms.dir = tmp_strdup(prms.dir); #else { const char * home_drv = getenv("HOMEDRIVE"); const char * home_dir = getenv("HOMEPATH"); if (home_drv && home_dir) { prms.dir = tmp_strdup2(home_drv, home_dir); } } #endif prms.exe = exec; prms.args = (char **)args; prms.service = TERMINALS; prms.use_terminal = 1; prms.exit_cb = terminal_exited; prms.exit_args = term; if (err == 0 && start_process(c, &prms, &selfattach, &term->prs) < 0) err = errno; if (!err) { term->bcg = c->bcg; channel_lock_with_msg(term->channel = c, TERMINALS); strlcpy(term->pty_type, pty_type, sizeof(term->pty_type)); strlcpy(term->encoding, encoding, sizeof(term->encoding)); list_add_first(&term->link, &terms_list); assert(find_terminal(get_process_pid(term->prs)) == term); } else { assert(term->prs == NULL); loc_free(term); } /* write result back */ write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); if (err) { write_stringz(&c->out, "null"); } else { write_context(&c->out, get_process_pid(term->prs)); write_stream(&c->out, 0); } write_stream(&c->out, MARKER_EOM); }
static void write_context(OutputStream * out, int tid) { Terminal * term = find_terminal(tid); const char * id = NULL; write_stream(out, '{'); if (term != NULL) { unsigned ws_col = 0; unsigned ws_row = 0; get_process_tty_win_size(term->prs, &ws_col, &ws_row); json_write_string(out, "ProcessID"); write_stream(out, ':'); json_write_string(out, pid2id(get_process_pid(term->prs), 0)); write_stream(out, ','); if (*term->pty_type) { json_write_string(out, "PtyType"); write_stream(out, ':'); json_write_string(out, term->pty_type); write_stream(out, ','); } if (*term->encoding) { json_write_string(out, "Encoding"); write_stream(out, ':'); json_write_string(out, term->encoding); write_stream(out, ','); } json_write_string(out, "Width"); write_stream(out, ':'); json_write_ulong(out, ws_col); write_stream(out, ','); json_write_string(out, "Height"); write_stream(out, ':'); json_write_ulong(out, ws_row); write_stream(out, ','); id = get_process_stream_id(term->prs, 0); if (id) { json_write_string(out, "StdInID"); write_stream(out, ':'); json_write_string(out, id); write_stream(out, ','); } id = get_process_stream_id(term->prs, 1); if (id) { json_write_string(out, "StdOutID"); write_stream(out, ':'); json_write_string(out, id); write_stream(out, ','); } id = get_process_stream_id(term->prs, 2); if (id) { json_write_string(out, "StdErrID"); write_stream(out, ':'); json_write_string(out, id); write_stream(out, ','); } } json_write_string(out, "ID"); write_stream(out, ':'); json_write_string(out, tid2id(tid)); write_stream(out, '}'); }
int main(int argc, char *argv[]) { useconds_t ts = 0; char *target = NULL; pid_t min_pid = getpid(); int c = 0, pid = 0, gdb = 0, ret_val = EXIT_FAILURE; int long_opt_index = 0; char *short_options = "p:t:gh"; struct option long_options[] = { { "pid", required_argument, NULL, 'p' }, { "time", required_argument, NULL, 't' }, { "gdb", no_argument, NULL, 'g' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; if(argc < 2) { usage(argv[0]); goto end; } while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'p': min_pid = atoi(optarg); break; case 't': ts = atoi(optarg); break; case 'g': gdb = 1; break; default: usage(argv[0]); goto end; } } target = argv[argc-1]; printf("Waiting for process '%s' with a pid greater than %d\n", target, min_pid); while((pid = get_process_pid(target, min_pid)) == -1) { } usleep(ts); if(kill(pid, SIGSTOP) == -1) { perror("kill"); } else { printf("%s (pid %d) has been paused.\n", target, pid); if(gdb) { execute_process(pid); } ret_val = EXIT_SUCCESS; } end: return ret_val; }