diff options
author | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2010-04-13 18:44:48 +0200 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2010-04-13 18:44:48 +0200 |
commit | 7fab518ce3dfefbe3ef99a78f28041f64d3ec542 (patch) | |
tree | 540c122eb533ea03bb7ab5d3bd950852700042c8 | |
parent | 62cf29bcb2cf185692c352c384650d1d950bb4c4 (diff) | |
download | tsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.tar.gz tsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.tar.xz tsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.zip |
support for tty list, initial tsnid
-rw-r--r-- | include/linux/tsnif.h | 2 | ||||
-rw-r--r-- | src/fsm.c | 18 | ||||
-rw-r--r-- | src/intf.c | 36 | ||||
-rw-r--r-- | src/intf.h | 3 | ||||
-rw-r--r-- | src/trans-libnl.c | 10 | ||||
-rw-r--r-- | src/tsnif.c | 24 | ||||
-rw-r--r-- | src/tsnifd.c | 231 |
7 files changed, 290 insertions, 34 deletions
diff --git a/include/linux/tsnif.h b/include/linux/tsnif.h index c38073f..efb426e 100644 --- a/include/linux/tsnif.h +++ b/include/linux/tsnif.h @@ -39,12 +39,12 @@ static struct nla_policy var[TSNIF_ATTR_MAX + 1] = { \ enum { TSNIF_CMD_ATTACH, TSNIF_CMD_DETACH, - TSNIF_CMD_RELEASE, TSNIF_CMD_MGROUP, TSNIF_CMD_TGROUP, TSNIF_CMD_DATA, TSNIF_CMD_TTY_CREATE, TSNIF_CMD_TTY_RELEASE, + TSNIF_CMD_TTY_LIST, __TSNIF_CMD_MAX, }; @@ -12,6 +12,7 @@ static int process_release(struct tsnif_handle *h, struct tsnif_term *term) term->state = TSNIF_INTF_STATE_DONE; + TSNIF_DEBUG("type %d, idx %d\n", term->type, term->idx); return h->ops->cb_release(term); } @@ -75,10 +76,6 @@ static int attach(struct tsnif_handle *h, err = process_tgroup(h, term, msg->group); break; - case TSNIF_CMD_RELEASE: - err = process_release(h, term); - break; - case TSNIF_CMD_ATTACH: /* got attach ack, do nothing */ if (msg->ack) @@ -118,10 +115,6 @@ static int detach(struct tsnif_handle *h, err = process_error(h, term, msg->error); break; - case TSNIF_CMD_RELEASE: - err = process_release(h, term); - break; - case TSNIF_CMD_DATA: /* ignore DATA msg when in DETACH state */ break; @@ -143,10 +136,6 @@ static int data(struct tsnif_handle *h, return 0; switch(msg->cmd) { - case TSNIF_CMD_RELEASE: - err = process_release(h, term); - break; - case TSNIF_CMD_DATA: err = process_data(h, term, msg); break; @@ -165,6 +154,11 @@ int fsm_process(struct tsnif_handle *h, TSNIF_DEBUG("got cmd %d for term type %d, idx %d, state %d\n", msg->cmd, term->type, term->idx, term->state); + /* we can get the release command in any state, + * so let's handle it globaly here */ + if (msg->cmd == TSNIF_CMD_TTY_RELEASE) + return process_release(h, term); + switch(term->state) { case TSNIF_INTF_STATE_NEW: return new(h, term, msg); @@ -29,11 +29,12 @@ static int process_notify(struct tsnif_handle *h, struct trans_msg *msg) if (!h->ops || !h->ops->cb_notify) return -1; + /* otherwise return fake one */ memset(&term, 0x0, sizeof(term)); term.type = msg->type; term.idx = msg->idx; term.handle = h; - term.state = TSNIF_INTF_STATE_NEW; + term.state = TSNIF_INTF_STATE_NONE; return h->ops->cb_notify(&term, msg->cmd); } @@ -56,18 +57,29 @@ static int trans_cb(struct trans_handle *h, struct trans_msg *msg) handle = container_of(h, struct tsnif_handle, trans); - /* then non term related bussines */ + /* do we have this term */ + term = term_find(handle, msg->type, msg->idx); + + /* non term related bussines */ switch(msg->cmd) { - case TSNIF_CMD_TTY_CREATE: case TSNIF_CMD_TTY_RELEASE: + + /* if we are handling the term, + * let's fsm do the job */ + if (term) + break; + + /* falling throught intentionaly */ + + case TSNIF_CMD_TTY_CREATE: + case TSNIF_CMD_TTY_LIST: return process_notify(handle, msg); case TSNIF_CMD_MGROUP: return process_mgroup(handle, msg); } - /* and term it is now */ - term = term_find(handle, msg->type, msg->idx); + /* no term no job here */ if (!term) return -ENODEV; @@ -78,6 +90,8 @@ static int init_mgroup(struct tsnif_handle *h) { struct trans_msg msg; + TSNIF_DEBUG("sending mgroup command\n"); + msg.cmd = TSNIF_CMD_MGROUP; return trans_send(&h->trans, &msg); } @@ -179,3 +193,15 @@ int tsnif_detach(struct tsnif_term *term) return trans_send(&h->trans, &msg); } + +int tsnif_list(struct tsnif_handle *h) +{ + struct trans_msg msg; + + TSNIF_DEBUG("sending list command\n"); + + memset(&msg, 0x0, sizeof(msg)); + msg.cmd = TSNIF_CMD_TTY_LIST; + + return trans_send(&h->trans, &msg); +} @@ -10,6 +10,8 @@ #include "trans.h" enum { + /* no state - notify state */ + TSNIF_INTF_STATE_NONE = 0, /* created, added to the list */ TSNIF_INTF_STATE_NEW = 1, /* attach is sent, waiting for TGROUP msg */ @@ -62,6 +64,7 @@ int tsnif_init(struct tsnif_handle *h, struct tsnif_ops *ops); int tsnif_close(struct tsnif_handle *h); int tsnif_process(struct tsnif_handle *h); int tsnif_fd(struct tsnif_handle *h); +int tsnif_list(struct tsnif_handle *h); /* term functions */ int tsnif_term_add(struct tsnif_handle *h, struct tsnif_term *term, diff --git a/src/trans-libnl.c b/src/trans-libnl.c index c6e3b90..61428ca 100644 --- a/src/trans-libnl.c +++ b/src/trans-libnl.c @@ -50,8 +50,6 @@ static int process_cb(struct trans_handle *h, struct trans_msg *m, time = (struct timespec*) nla_data(attrs[TSNIF_ATTR_TIME]); m->data.time = *(time); - TSNIF_DEBUG("time1 %ld %ld\n", time->tv_sec, time->tv_nsec); - TSNIF_DEBUG("time2 %ld\n", m->data.time.tv_sec); } if (attrs[TSNIF_ATTR_WS]) { @@ -68,7 +66,7 @@ static int process_cb(struct trans_handle *h, struct trans_msg *m, TSNIF_DEBUG("got cmd %d, type %d, idx %d, " "ack %d, err %d\n", - m->cmd, m->idx, m->type, + m->cmd, m->type, m->idx, m->ack, m->err); return h->cb(h, m) ? NL_STOP : NL_OK; @@ -78,8 +76,6 @@ static int err_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg) { struct trans_msg m; - TSNIF_DEBUG("got error cb\n"); - memset(&m, 0x0, sizeof(m)); if (nlerr->error == TSNIF_OK) @@ -89,6 +85,9 @@ static int err_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg) m.error = nlerr->error; } + TSNIF_DEBUG("got error cb - ack %d, err %d, error %d\n", + m.ack, m.err, m.error); + return process_cb(arg, &m, &nlerr->msg); } @@ -178,6 +177,7 @@ int trans_send(struct trans_handle *h, struct trans_msg *m) if ((m->cmd != TSNIF_CMD_ATTACH) && (m->cmd != TSNIF_CMD_DETACH) && + (m->cmd != TSNIF_CMD_TTY_LIST) && (m->cmd != TSNIF_CMD_MGROUP)) return -EINVAL; diff --git a/src/tsnif.c b/src/tsnif.c index 643424f..5b2946f 100644 --- a/src/tsnif.c +++ b/src/tsnif.c @@ -263,27 +263,31 @@ int main(int argc, char **argv) while(!killed) { fd_set rfds; struct timeval tv = { 1, 0}; - int ts_fd = tsnif_fd(&handle), ret; + int ts_fd = tsnif_fd(&handle); int in_fd = 0; FD_ZERO(&rfds); FD_SET(ts_fd, &rfds); FD_SET(in_fd, &rfds); - ret = select(ts_fd + 1, &rfds, NULL, NULL, &tv); - if (ret == -1) { + err = select(ts_fd + 1, &rfds, NULL, NULL, &tv); + if (err == -1) { perror("select()"); continue; - } else if (!ret) + } else if (!err) continue; - if (FD_ISSET(ts_fd, &rfds) && - tsnif_process(&handle)) - longjmp(env, 3); + if (FD_ISSET(ts_fd, &rfds)) { + err = tsnif_process(&handle); + if (err) + longjmp(env, 3); + } - if (FD_ISSET(in_fd, &rfds) && - process_input()) - longjmp(env, 3); + if (FD_ISSET(in_fd, &rfds)) { + err = process_input(); + if (err) + longjmp(env, 3); + } } longjmp(env, 3); diff --git a/src/tsnifd.c b/src/tsnifd.c index 5864387..14127b4 100644 --- a/src/tsnifd.c +++ b/src/tsnifd.c @@ -1,7 +1,236 @@ #include <stdio.h> +#include <sys/select.h> +#include <unistd.h> +#include <termios.h> +#include <getopt.h> +#include <errno.h> +#include <setjmp.h> +#include <signal.h> -int main(int argc, char **argv) +#include "autoconf.h" +#include "intf.h" +#include "storage.h" +#include "misc.h" + +extern int tsnif_debug; + +static struct tsnif_storage_opts init_storage_opts = { + .flags = TSNIF_STORAGE_OPT_WRITE, + .size_max = 1024*1024, +}; + +static struct tsnif_handle handle; + +struct terminal { + /* interface term */ + struct tsnif_term term; + + /* storage */ + struct tsnif_storage_opts storage_opts; + struct tsnif_storage_handle storage_handle; +}; + +static int foreground = 0; +static int killed = 0; +static char *store_dir = "/var/log/tsnid/"; + +int terminal_add(struct tsnif_term *term) +{ + struct terminal *t; + int err; + + TSNIF_DEBUG("type %d, idx %d\n", term->type, term->idx); + + if (term->type != TSNIF_TYPE_PTY) + return 0; + + t = malloc(sizeof(*t)); + if (!t) + return -ENOMEM; + + memset(t, 0x0, sizeof(*t)); + + err = tsnif_term_add(&handle, &t->term, term->type, term->idx); + if (err) { + free(t); + return err; + } + + return tsnif_attach(&t->term); +} + +int terminal_del(struct tsnif_term *term) +{ + struct terminal *t; + int err; + + TSNIF_DEBUG("type %d, idx %d\n", term->type, term->idx); + + err = tsnif_term_del(&handle, term); + if (err) { + /* TODO do smth smart */ + } + + t = container_of(term, struct terminal, term); + free(t); + + return err; +} + +static int data_cb(struct tsnif_term* term, struct tsnif_data *data) +{ + struct terminal *t; + + t = container_of(term, struct terminal, term); + return 0; +} + +static int err_cb(struct tsnif_term *term, int err) +{ + return err; +} + +static int release_cb(struct tsnif_term *term) +{ + return terminal_del(term); +} + +static int notify_cb(struct tsnif_term *term, int action) +{ + int err = 0; + + switch(action) { + case TSNIF_CMD_TTY_RELEASE: + printf("not watched terminal released - type %d, idx %d\n", + term->type, term->idx); + break; + + case TSNIF_CMD_TTY_CREATE: + case TSNIF_CMD_TTY_LIST: + err = terminal_add(term); + break; + + default: + err = -EINVAL; + } + return err; +} + +struct tsnif_ops ops = { + .cb_data = data_cb, + .cb_err = err_cb, + .cb_release = release_cb, + .cb_notify = notify_cb, +}; + +static void sig_handler(int sig) +{ + printf("killed\n"); + killed = 1; +} + +static void usage() { + printf("tsnifd [-dfvhs]\n"); + _exit(-1); +} + +static int get_args(int argc, char **argv) +{ + while (1) { + int c; + int option_index = 0; + static struct option long_options[] = { + {"version", no_argument, 0, 'v'}, + {"debug", no_argument, 0, 'd'}, + {"foreground", no_argument, 0, 'f'}, + {"store-dir", required_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "t:i:s:vdh", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'v': + printf("tsnif "CONFIG_TSNIF_VER"\n"); + break; + + case 'd': + tsnif_debug = 1; + break; + + case 'f': + foreground = 1; + break; + + case 's': + store_dir = optarg; + break; + + case 'h': + usage(); + break; + + default: + printf("unknown option '%c'", c); + } /* switch(c) */ + } /* while(1) */ + return 0; } + +int main(int argc, char **argv) +{ + int err, ret; + jmp_buf env; + + if (get_args(argc, argv)) + usage(); + + err = tsnif_init(&handle, &ops); + if (err) + return err; + + if ((ret = setjmp(env))) { + + tsnif_close(&handle); + printf("done err = %d\n", err); + return err; + } + + err = tsnif_list(&handle); + if (err) + longjmp(env, 1); + + signal(SIGINT, sig_handler); + + while(!killed) { + fd_set rfds; + struct timeval tv = { 1, 0}; + int ts_fd = tsnif_fd(&handle); + + FD_ZERO(&rfds); + FD_SET(ts_fd, &rfds); + + err = select(ts_fd + 1, &rfds, NULL, NULL, &tv); + if (err == -1) { + perror("select()"); + continue; + } else if (!err) + continue; + + if (FD_ISSET(ts_fd, &rfds)) { + err = tsnif_process(&handle); + if (err) + longjmp(env, 3); + } + } + + longjmp(env, 3); +} |