EditBuffer *new_shell_buffer(const char *name, const char *path, const char **argv, int is_shell) { ShellState *s; EditBuffer *b, *b_color; b = eb_new("", BF_SAVELOG); if (!b) return NULL; set_buffer_name(b, name); /* ensure that the name is unique */ eb_set_charset(b, &charset_vt100); s = malloc(sizeof(ShellState)); if (!s) { eb_free(b); return NULL; } memset(s, 0, sizeof(ShellState)); b->priv_data = s; b->close = shell_close; eb_add_callback(b, eb_offset_callback, &s->cur_offset); s->b = b; s->pty_fd = -1; s->pid = -1; s->is_shell = is_shell; s->qe_state = &qe_state; tty_init(s); /* add color buffer */ if (is_shell) { b_color = eb_new("*color*", BF_SYSTEM); if (!b_color) { eb_free(b); free(s); return NULL; } /* no undo info in this color buffer */ b_color->save_log = 0; eb_add_callback(b, shell_color_callback, s); s->b_color = b_color; } /* launch shell */ if (run_process(path, argv, &s->pty_fd, &s->pid) < 0) { eb_free(b); return NULL; } set_read_handler(s->pty_fd, shell_read_cb, s); set_pid_handler(s->pid, shell_pid_cb, s); return b; }
void shell_pid_cb(void *opaque, int status) { ShellState *s = opaque; EditBuffer *b = s->b; QEmacsState *qs = s->qe_state; EditState *e; char buf[1024]; if (s->is_shell) { snprintf(buf, sizeof(buf), "\nProcess shell finished\n"); } else { time_t ti; char *time_str; ti = time(NULL); time_str = ctime(&ti); if (WIFEXITED(status)) status = WEXITSTATUS(status); else status = -1; if (status == 0) { snprintf(buf, sizeof(buf), "\nCompilation finished at %s", time_str); } else { snprintf(buf, sizeof(buf), "\nCompilation exited abnormally with code %d at %s", status, time_str); } } eb_write(b, b->total_size, buf, strlen(buf)); set_pid_handler(s->pid, NULL, NULL); s->pid = -1; /* no need to leave the pty opened */ if (s->pty_fd >= 0) { set_read_handler(s->pty_fd, NULL, NULL); close(s->pty_fd); s->pty_fd = -1; } /* remove shell input mode */ s->grab_keys = 0; qe_ungrab_keys(); for (e = qs->first_window; e != NULL; e = e->next_window) { if (e->b == b) e->interactive = 0; } edit_display(qs); dpy_flush(qs->screen); }
static void shell_close(EditBuffer *b) { ShellState *s = b->priv_data; int status; eb_free_callback(b, eb_offset_callback, &s->cur_offset); if (s->pid != -1) { kill(s->pid, SIGINT); /* wait first 100 ms */ usleep(100 * 1000); if (waitpid(s->pid, &status, WNOHANG) != s->pid) { /* if still not killed, then try harder (useful for shells) */ kill(s->pid, SIGKILL); while (waitpid(s->pid, &status, 0) != s->pid); } s->pid = -1; } if (s->pty_fd >= 0) { set_read_handler(s->pty_fd, NULL, NULL); } free(s); }
static int qt_init(QEditScreen *s, int w, int h) { QEStyleDef default_style; int xsize, ysize, font_ysize; QEQtContext *ctx; ctx = new QEQtContext(); if (ctx == NULL) { return -1; } s->priv_data = ctx; s->media = CSS_MEDIA_SCREEN; s->bitmap_format = QEBITMAP_FORMAT_RGBA32; int event_pipe[2]; if (pipe(event_pipe) < 0) return -1; fcntl(event_pipe[0], F_SETFD, FD_CLOEXEC); fcntl(event_pipe[1], F_SETFD, FD_CLOEXEC); ctx->events_rd = event_pipe[0]; ctx->events_wr = event_pipe[1]; set_read_handler(event_pipe[0], qt_handle_event, s); /* At this point, we should be able to ask for metrics */ if (font_ptsize) qe_styles[0].font_size = font_ptsize; get_style(NULL, &default_style, 0); QEFont *font = qt_open_font(s, default_style.font_style, default_style.font_size); if (!font) { fprintf(stderr, "Could not open default font\n"); exit(1); } QFont *qt_font = (QFont *)font->priv_data; QFontMetrics fm(*qt_font); font_xsize = fm.width("n"); font_ysize = fm.height(); qt_close_font(s, &font); if (w == 0) w = 80; if (h == 0) h = 25; xsize = w * font_xsize; ysize = h * font_ysize; s->width = xsize; s->height = ysize; s->charset = &charset_utf8; s->clip_x1 = 0; s->clip_y1 = 0; s->clip_x2 = s->width; s->clip_y2 = s->height; ctx->view->resize(xsize, ysize); return 2; }