#include #include #include #include #include #include #include #include #include "autoconf.h" #include "intf.h" #include "storage.h" #include "misc.h" #include "debug.h" static struct tsnif_handle handle; static struct tsnif_term term; static struct tsnif_storage_opts storage_opts = { .flags = TSNIF_STORAGE_OPT_WRITE, .size_max = 1024*1024, }; static struct tsnif_storage_handle storage_handle; static int killed = 0; static int store = 0; static int type = -1; static int idx = -1; static int display_slave = 1; static int display_master = 0; static char *storage_file = NULL; static int display_pty(int flags) { if ((flags == TSNIF_FLAGS_PTY_SLAVE) && !display_slave) return 0; if ((flags == TSNIF_FLAGS_PTY_MASTER) && !display_master) return 0; return 1; } static int store_data(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(&storage_handle, &rec); } static int data_cb(struct tsnif_term* term, struct tsnif_data *data) { if (store) store_data(data); /* rule out unwanted PTY channel */ if ((term->type == TSNIF_TYPE_PTY) && !display_pty(data->flags)) return 0; fwrite(data->ptr, data->len, 1, stdout); fflush(NULL); return 0; } static int err_cb(struct tsnif_term *term, int err) { return err; } static int release_cb(struct tsnif_term *term) { return -1; } static int notify_cb(struct tsnif_term *term, int action) { return 0; } struct tsnif_ops ops = { .cb_data = data_cb, .cb_err = err_cb, .cb_release = release_cb, .cb_notify = notify_cb, }; static void usage() { printf("tsnif -t -i [ -s ]\n"); printf(" where types can be 'tty', 'ttys' or 'pty'\n"); _exit(-1); } static void sig_handler(int sig) { printf("killed\n"); killed = 1; } static int get_type(char *optarg) { int i; char *types[TSNIF_TYPE_MAX] = { "tty", "ttys", "pty", }; for(i = 0; i < TSNIF_TYPE_MAX; i++) if (!strcmp(optarg, types[i])) break; return i; } static int get_args(int argc, char **argv) { int ret = 0; while (1) { int c; int option_index = 0; static struct option long_options[] = { {"type", required_argument, 0, 't'}, {"idx", required_argument, 0, 'i'}, {"store", required_argument, 0, 's'}, {"version", no_argument, 0, 'V'}, {"debug", required_argument, 0, 'd'}, {"verbose", required_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "t:i:s:v:d:hV", long_options, &option_index); if (c == -1) break; switch (c) { case 't': type = get_type(optarg); if (type == TSNIF_TYPE_MAX) return -1; break; case 'i': errno = 0; idx = strtol(optarg, (char **) NULL, 10); if (errno) { perror("strtol failed"); printf("strtol failed\n"); return -1; } break; case 's': storage_file = optarg; store = 1; break; case 'V': print_version(argv[0]); break; case 'v': ret = debug_parse_flags(0, optarg); break; case 'd': ret = debug_parse_flags(1, optarg); break; case 'h': usage(); break; default: printf("unknown option '%c'", c); } /* switch(c) */ } /* while(1) */ if ((type == -1) || (idx == -1)) return -EINVAL; return ret; } static int process_input(void) { int c = getchar(); switch(c) { case 's': display_slave = !display_slave; break; case 'm': display_master = !display_master; break; case 'q': return -1; default: return 0; } printf("\ntsnif display [%s%s]\n", display_master ? "M" : "", display_slave ? "S" : ""); 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))) { if (ret > 2) { set_term(1); if (store) tsnif_storage_close(&storage_handle); } if (ret > 1) { tsnif_detach(&term); } tsnif_close(&handle); printf("done err = %d\n", err); return err; } /* attach the term */ err = tsnif_term_add(&handle, &term, type, idx); if (err) longjmp(env, 1); err = tsnif_attach(&term); if (err) longjmp(env, 1); storage_opts.term_type = type; /* initialize storage unit if needed */ if (store) { err = tsnif_storage_init(&storage_handle, &storage_opts, storage_file); if (err) longjmp(env, 2); } set_term(0); signal(SIGINT, sig_handler); while(!killed) { fd_set rfds; struct timeval tv = { 1, 0}; int ts_fd = tsnif_fd(&handle); int in_fd = 0; FD_ZERO(&rfds); FD_SET(ts_fd, &rfds); FD_SET(in_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); } if (FD_ISSET(in_fd, &rfds)) { err = process_input(); if (err) longjmp(env, 3); } } longjmp(env, 3); }