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 <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-09-26 21:24:34 +02:00
parent 9c48153e30
commit 89cb239fce
3 changed files with 47 additions and 5 deletions

View File

@ -37,7 +37,6 @@
#include <unistd.h>
#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;

View File

@ -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);

View File

@ -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);