From 89cb239fce77d248eb320f495d3c583f8aba1419 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 26 Sep 2012 21:24:34 +0200 Subject: [PATCH] pty: set argv via helper function This makes the pty layer independent of kmscon global state. This allows us to use it in other applications bundled with kmscon. There is still some work to do to make it fully independent so we can integrate it into TSM. But that's not really needed, yet. Signed-off-by: David Herrmann --- src/pty.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- src/pty.h | 1 + src/terminal.c | 4 ++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/pty.c b/src/pty.c index 60a9fb1..2a1b3b8 100644 --- a/src/pty.c +++ b/src/pty.c @@ -37,7 +37,6 @@ #include #include "eloop.h" #include "log.h" -#include "main.h" #include "pty.h" #include "shl_ring.h" @@ -59,6 +58,7 @@ struct kmscon_pty { void *data; char *term; + char **argv; }; int kmscon_pty_new(struct kmscon_pty **out, kmscon_pty_input_cb input_cb, @@ -114,6 +114,7 @@ void kmscon_pty_unref(struct kmscon_pty *pty) log_debug("free pty object"); kmscon_pty_close(pty); + free(pty->argv); free(pty->term); shl_ring_free(pty->msgbuf); ev_eloop_unref(pty->eloop); @@ -136,6 +137,40 @@ int kmscon_pty_set_term(struct kmscon_pty *pty, const char *term) return 0; } +int kmscon_pty_set_argv(struct kmscon_pty *pty, char **argv) +{ + char **t, *off; + unsigned int size, i; + + if (!pty || !argv || !*argv || !**argv) + return -EINVAL; + + size = 0; + for (i = 0; argv[i]; ++i) + size += strlen(argv[i]) + 1; + ++i; + + size += i * sizeof(char*); + + t = malloc(size); + if (!t) + return -ENOMEM; + free(pty->argv); + pty->argv = t; + + off = (char*)t + i * sizeof(char*); + while (*argv) { + *t++ = off; + for (i = 0; argv[0][i]; ++i) + *off++ = argv[0][i]; + *off++ = 0; + argv++; + } + *t = NULL; + + return 0; +} + int kmscon_pty_get_fd(struct kmscon_pty *pty) { if (!pty) @@ -186,15 +221,17 @@ static void pty_close(struct kmscon_pty *pty, bool user) } static void __attribute__((noreturn)) -exec_child(int pty_master, const char *term) +exec_child(int pty_master, const char *term, char **argv) { if (!term) term = "vt220"; + if (!argv) + argv = (char*[]){ "/bin/sh", "-l", NULL }; setenv("TERM", term, 1); - execvp(kmscon_conf.argv[0], kmscon_conf.argv); + execvp(argv[0], argv); - log_err("failed to exec child %s: %m", kmscon_conf.argv[0]); + log_err("failed to exec child %s: %m", argv[0]); exit(EXIT_FAILURE); } @@ -309,7 +346,7 @@ static int pty_spawn(struct kmscon_pty *pty, int master, return -errno; case 0: setup_child(master, &ws); - exec_child(pty->fd, pty->term); + exec_child(pty->fd, pty->term, pty->argv); exit(EXIT_FAILURE); default: pty->fd = master; diff --git a/src/pty.h b/src/pty.h index 42558a1..b8eef09 100644 --- a/src/pty.h +++ b/src/pty.h @@ -54,6 +54,7 @@ int kmscon_pty_new(struct kmscon_pty **out, kmscon_pty_input_cb input_cb, void kmscon_pty_ref(struct kmscon_pty *pty); void kmscon_pty_unref(struct kmscon_pty *pty); int kmscon_pty_set_term(struct kmscon_pty *pty, const char *term); +int kmscon_pty_set_argv(struct kmscon_pty *pty, char **argv); int kmscon_pty_get_fd(struct kmscon_pty *pty); void kmscon_pty_dispatch(struct kmscon_pty *pty); diff --git a/src/terminal.c b/src/terminal.c index 027f067..526f34b 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -454,6 +454,10 @@ int kmscon_terminal_new(struct kmscon_terminal **out, if (ret) goto err_pty; + ret = kmscon_pty_set_argv(term->pty, kmscon_conf.argv); + if (ret) + goto err_pty; + ret = ev_eloop_new_fd(term->eloop, &term->ptyfd, kmscon_pty_get_fd(term->pty), EV_READABLE, pty_event, term);