summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-14 11:59:58 +0200
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-14 11:59:58 +0200
commit1935c50b0f3af15aed865009c728e5eec06c12ac (patch)
treeef916f58887688da51de95165dbab6032237b40c
parentf6c0943a2b6e8e0a9fc0939dbe5628ecca8d78e4 (diff)
downloadtsnif-1935c50b0f3af15aed865009c728e5eec06c12ac.tar.gz
tsnif-1935c50b0f3af15aed865009c728e5eec06c12ac.tar.xz
tsnif-1935c50b0f3af15aed865009c728e5eec06c12ac.zip
store support for tsnifd
-rw-r--r--src/fsm.c7
-rw-r--r--src/intf.c14
-rw-r--r--src/intf.h5
-rw-r--r--src/tsnifd.c184
4 files changed, 191 insertions, 19 deletions
diff --git a/src/fsm.c b/src/fsm.c
index d161145..276fd60 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -104,10 +104,9 @@ static int detach(struct tsnif_handle *h,
switch(msg->cmd) {
case TSNIF_CMD_DETACH:
- if (msg->ack) {
- term->state = TSNIF_INTF_STATE_DONE;
- break;
- }
+ if (msg->ack)
+ return process_release(h, term);
+
err = -EINVAL;
if (!msg->err)
break;
diff --git a/src/intf.c b/src/intf.c
index 7f1e98b..6c55571 100644
--- a/src/intf.c
+++ b/src/intf.c
@@ -205,3 +205,17 @@ int tsnif_list(struct tsnif_handle *h)
return trans_send(&h->trans, &msg);
}
+
+int tsnif_enum(struct tsnif_handle *h, cb_tsnif_enum_t cb)
+{
+ struct tsnif_term *term, *t;
+ int err = 0;
+
+ list_for_each_entry_safe(term, t, &h->terms, list) {
+ err = cb(term);
+ if (err)
+ break;
+ }
+
+ return err;;
+}
diff --git a/src/intf.h b/src/intf.h
index 539b0de..0723be7 100644
--- a/src/intf.h
+++ b/src/intf.h
@@ -59,6 +59,8 @@ struct tsnif_handle {
struct trans_handle trans;
};
+typedef int(*cb_tsnif_enum_t)(struct tsnif_term *term);
+
/* handle functions */
int tsnif_init(struct tsnif_handle *h, struct tsnif_ops *ops);
int tsnif_close(struct tsnif_handle *h);
@@ -73,6 +75,9 @@ int tsnif_term_del(struct tsnif_handle *h, struct tsnif_term *term);
int tsnif_attach(struct tsnif_term *term);
int tsnif_detach(struct tsnif_term *term);
+#define tsnif_for_each(term, t, handle) \
+ list_for_each_entry_safe(term, t, (&handle->terms), list)
+
extern int tsnif_debug;
#define TSNIF_DEBUG(fmt, args...) \
diff --git a/src/tsnifd.c b/src/tsnifd.c
index 14127b4..22b6da5 100644
--- a/src/tsnifd.c
+++ b/src/tsnifd.c
@@ -7,12 +7,17 @@
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
#include "autoconf.h"
#include "intf.h"
#include "storage.h"
#include "misc.h"
+
extern int tsnif_debug;
static struct tsnif_storage_opts init_storage_opts = {
@@ -27,23 +32,124 @@ struct terminal {
struct tsnif_term term;
/* storage */
+ char *file;
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/";
+static char *store_dir = "/var/log/tsnid";
+
+static char *types[TSNIF_TYPE_MAX] = {
+ "tty", "ttys", "pty"
+};
+
+static char *type_get(int type)
+{
+ if ((type >= TSNIF_TYPE_MAX) ||
+ (type < 0))
+ return NULL;
+
+ return types[type];
+}
+
+static int dir_get(char *path)
+{
+ struct stat st;
+ int err;
+
+ if (!stat(path, &st))
+ return 0;
+
+ err = mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR);
+ if (err) {
+ perror("mkdir failed");
+ return err;
+ }
+
+ return 0;
+
+}
+
+static char *file_get(int type, int idx)
+{
+ struct timeval tv;
+ struct tm *tm;
+#define MAXPATH 1024
+ static char path[MAXPATH];
+ char *type_str;
+ int len;
+
+ if (dir_get(store_dir))
+ return NULL;
+
+ type_str = type_get(type);
+ if (!type_str)
+ return NULL;
+
+ len = snprintf(path, MAXPATH, "%s/%s", store_dir, type_str);
+
+ if (dir_get(path))
+ return NULL;
+
+ if (-1 == gettimeofday(&tv, NULL)) {
+ perror("gettimeofday failed");
+ return NULL;
+ }
+
+ tm = localtime(&tv.tv_sec);
+ if (!tm) {
+ perror("localtime failed");
+ return NULL;
+ }
+
+ snprintf(path + len, MAXPATH - len,
+ "/%d-%02d.%02d.%02d_%02d:%02d:%02d.%03lu-alive",
+ idx,
+ tm->tm_mday,
+ tm->tm_mon + 1,
+ (tm->tm_year + 1900) % 100,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ tv.tv_usec / 1000);
+
+ return path;
+}
+
+static int file_put(char *name)
+{
+ char *new = strdup(name);
+ char *p;
+ int err;
-int terminal_add(struct tsnif_term *term)
+ p = strrchr(new, '-');
+ if (!p)
+ return -1;
+
+ sprintf(p, "%s", ".tsnif");
+
+ TSNIF_DEBUG("putting to %s\n", new);
+
+ err = rename(name, new);
+ free(new);
+ return err;
+}
+
+static int terminal_add(struct tsnif_term *term)
{
struct terminal *t;
int err;
+ char *file;
TSNIF_DEBUG("type %d, idx %d\n", term->type, term->idx);
- if (term->type != TSNIF_TYPE_PTY)
- return 0;
+ /* XXX debug gets only PTY XXX */
+ if (tsnif_debug) {
+ if (term->type != TSNIF_TYPE_PTY)
+ return 0;
+ }
t = malloc(sizeof(*t));
if (!t)
@@ -57,25 +163,54 @@ int terminal_add(struct tsnif_term *term)
return err;
}
+ file = file_get(term->type, term->idx);
+ if (!file) {
+ tsnif_term_del(&handle, &t->term);
+ free(t);
+ return -1;
+ }
+
+ TSNIF_DEBUG("storing to %s\n", file);
+
+ t->file = strdup(file);
+ t->storage_opts = init_storage_opts;
+
+ err = tsnif_storage_init(&t->storage_handle,
+ &t->storage_opts, file);
+
return tsnif_attach(&t->term);
}
-int terminal_del(struct tsnif_term *term)
+static 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 */
- }
+ tsnif_term_del(&handle, term);
t = container_of(term, struct terminal, term);
+
+ tsnif_storage_close(&t->storage_handle);
+ file_put(t->file);
+ free(t->file);
+
free(t);
- return err;
+ return 0;
+}
+
+static int store_data(struct tsnif_storage_handle *h, struct tsnif_data *data)
+{
+ struct tsnif_storage_rec rec = {
+ .ptr = data->ptr,
+ .len = data->len,
+ .flags = data->flags,
+ .time = data->time,
+ .ws = data->ws,
+ };
+
+ return tsnif_storage_write(h, &rec);
}
static int data_cb(struct tsnif_term* term, struct tsnif_data *data)
@@ -83,12 +218,13 @@ static int data_cb(struct tsnif_term* term, struct tsnif_data *data)
struct terminal *t;
t = container_of(term, struct terminal, term);
- return 0;
+
+ return store_data(&t->storage_handle, data);
}
static int err_cb(struct tsnif_term *term, int err)
{
- return err;
+ return terminal_del(term);
}
static int release_cb(struct tsnif_term *term)
@@ -117,6 +253,21 @@ static int notify_cb(struct tsnif_term *term, int action)
return err;
}
+static int release_terms(void)
+{
+ struct tsnif_term *term, *t;
+
+ tsnif_for_each(term, t, (&handle)) {
+ /* The ACK action (release cb) is never going
+ * to happen, since we are going down, * so we
+ * need to run terminal_del manually */
+ tsnif_detach(term);
+ terminal_del(term);
+ }
+
+ return 0;
+}
+
struct tsnif_ops ops = {
.cb_data = data_cb,
.cb_err = err_cb,
@@ -199,6 +350,9 @@ int main(int argc, char **argv)
if ((ret = setjmp(env))) {
+ if (ret > 1)
+ release_terms();
+
tsnif_close(&handle);
printf("done err = %d\n", err);
return err;
@@ -228,9 +382,9 @@ int main(int argc, char **argv)
if (FD_ISSET(ts_fd, &rfds)) {
err = tsnif_process(&handle);
if (err)
- longjmp(env, 3);
+ longjmp(env, 2);
}
}
- longjmp(env, 3);
+ longjmp(env, 2);
}