summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-13 18:44:48 +0200
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-13 18:44:48 +0200
commit7fab518ce3dfefbe3ef99a78f28041f64d3ec542 (patch)
tree540c122eb533ea03bb7ab5d3bd950852700042c8
parent62cf29bcb2cf185692c352c384650d1d950bb4c4 (diff)
downloadtsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.tar.gz
tsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.tar.xz
tsnif-7fab518ce3dfefbe3ef99a78f28041f64d3ec542.zip
support for tty list, initial tsnid
-rw-r--r--include/linux/tsnif.h2
-rw-r--r--src/fsm.c18
-rw-r--r--src/intf.c36
-rw-r--r--src/intf.h3
-rw-r--r--src/trans-libnl.c10
-rw-r--r--src/tsnif.c24
-rw-r--r--src/tsnifd.c231
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,
};
diff --git a/src/fsm.c b/src/fsm.c
index 9301918..d161145 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -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);
diff --git a/src/intf.c b/src/intf.c
index 8cb7e02..7f1e98b 100644
--- a/src/intf.c
+++ b/src/intf.c
@@ -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);
+}
diff --git a/src/intf.h b/src/intf.h
index 4404b16..539b0de 100644
--- a/src/intf.h
+++ b/src/intf.h
@@ -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);
+}