From a108c1aec43d1f2a5dac0984a5fe9aa4b1c74b91 Mon Sep 17 00:00:00 2001 From: toni Date: Tue, 13 Oct 2015 17:42:21 +0200 Subject: better ipc: using POSIX (semaphores && msg queues) --- main.c | 129 +++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 85 insertions(+), 44 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 670503e..c40265d 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "ui_ani.h" #include "ui_input.h" @@ -16,7 +19,9 @@ #include "config.h" -static bool ui_active = true; +static sem_t *sp_ui, *sp_input; +static mqd_t mq_passwd; + static void usage(char *arg0) @@ -51,23 +56,6 @@ check_fifo(char *fifo_path) return (false); } -/* stolen from http://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html */ -static int -input_timeout(int filedes, unsigned int seconds) -{ - fd_set set; - struct timeval timeout; - - /* Initialize the file descriptor set. */ - FD_ZERO (&set); - FD_SET (filedes, &set); - /* Initialize the timeout data structure. */ - timeout.tv_sec = seconds; - timeout.tv_usec = 0; - /* select returns 0 if timeout, 1 if input available, -1 if error. */ - return TEMP_FAILURE_RETRY(select(FD_SETSIZE, &set, NULL, NULL, &timeout)); -} - int run_cryptcreate(char *pass, char *crypt_cmd) { @@ -80,22 +68,65 @@ run_cryptcreate(char *pass, char *crypt_cmd) return (retval); } +void sigfunc(int signal) +{ + switch (signal) { + case SIGTERM: + case SIGKILL: + case SIGINT: + sem_trywait(sp_ui); + sem_trywait(sp_input); + break; + } +} + int main(int argc, char **argv) { - int ffd, c_status, opt; + int ret = EXIT_FAILURE, ffd = -1, c_status, opt, i_sval; pid_t child; char pbuf[MAX_PASSWD_LEN+1]; char *fifo_path = NULL; char *crypt_cmd = NULL; + struct timespec ts_sem_input; + struct mq_attr mq_attr; - memset(pbuf, '\0', MAX_PASSWD_LEN+1); + signal(SIGINT, sigfunc); + signal(SIGTERM, sigfunc); + signal(SIGKILL, sigfunc); + + if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) { + fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + if ( (sp_ui = sem_open(SEM_GUI, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED || + (sp_input = sem_open(SEM_INP, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED || +(mq_passwd = mq_open(MSQ_PWD, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, NULL)) == (mqd_t) -1 ) { + if ( errno == EEXIST ) { + fprintf(stderr, "%s: already started?\n", argv[0]); + } else { + fprintf(stderr, "%s: can not create semaphore: %d (%s)\n", argv[0], errno, strerror(errno)); + } + goto error; + } + if ( mq_getattr(mq_passwd, &mq_attr) == 0 ) { + mq_attr.mq_maxmsg = 2; + mq_attr.mq_msgsize = MAX_PASSWD_LEN; + if ( mq_setattr(mq_passwd, &mq_attr, NULL) != 0 ) { + fprintf(stderr, "%s: can not SET message queue attributes: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + } else { + fprintf(stderr, "%s: can not GET message queue attributes: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + memset(pbuf, '\0', MAX_PASSWD_LEN+1); while ((opt = getopt(argc, argv, "hf:c:")) != -1) { switch (opt) { case 'h': usage(argv[0]); - exit(EXIT_SUCCESS); + goto error; case 'f': fifo_path = strdup(optarg); break; @@ -104,56 +135,66 @@ main(int argc, char **argv) break; default: usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } } if (optind < argc) { fprintf(stderr, "%s: I dont understand you.\n\n", argv[0]); usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } if (fifo_path == NULL) fifo_path = strdup(DEFAULT_FIFO); if (check_fifo(fifo_path) == false) { usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } if ((ffd = open(fifo_path, O_NONBLOCK | O_RDWR)) < 0) { - fprintf(stderr, "fifo: %s\n", fifo_path); - perror("open"); - exit(EXIT_FAILURE); + fprintf(stderr, "%s: fifo '%s' error: %d (%s)\n", argv[0], fifo_path, errno, strerror(errno)); + goto error; } if ((child = fork()) == 0) { /* child */ - ui_active = true; - do_ui(ffd); - ui_active = false; + fclose(stderr); + /* Slave process: TUI */ + sem_post(sp_ui); + do_ui(); } else if (child > 0) { /* parent */ fclose(stdin); - while (input_timeout(ffd, 1) == 0) { - usleep(100000); - if (ui_active == true) { - // TODO: smthng + fclose(stdout); + /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */ + while ( sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0 ) { + if ( sem_getvalue(sp_input, &i_sval) == 0 && i_sval > 0 ) { + if (read(ffd, pbuf, MAX_PASSWD_LEN) > 0) { + if (run_cryptcreate(pbuf, crypt_cmd) != 0) { + fprintf(stderr, "cryptcreate error\n"); + } + } + } else if ( mq_receive(mq_passwd, pbuf, MAX_PASSWD_LEN, NULL) > 0 ) { +exit(77); } + usleep(100000); } - stop_ui(); wait(&c_status); - if (read(ffd, pbuf, MAX_PASSWD_LEN) > 0) { - if (run_cryptcreate(pbuf, crypt_cmd) != 0) { - fprintf(stderr, "cryptcreate error\n"); - } - } memset(pbuf, '\0', MAX_PASSWD_LEN+1); } else { /* fork error */ perror("fork"); - exit(EXIT_FAILURE); + goto error; } - close(ffd); + ret = EXIT_SUCCESS; +error: + if (ffd >= 0) close(ffd); if (crypt_cmd != NULL) free(crypt_cmd); - free(fifo_path); - return (EXIT_SUCCESS); + if (fifo_path != NULL) free(fifo_path); + sem_close(sp_ui); + sem_close(sp_input); + mq_close(mq_passwd); + sem_unlink(SEM_GUI); + sem_unlink(SEM_INP); + mq_unlink(MSQ_PWD); + exit(ret); } -- cgit v1.2.3 From d7071577be3f49b964c4d234024bf62328d0209d Mon Sep 17 00:00:00 2001 From: toni Date: Tue, 13 Oct 2015 17:42:21 +0200 Subject: better ipc: using POSIX (semaphores && msg queues) --- .gitignore | 1 + Makefile | 2 +- config.h | 4 ++ main.c | 129 +++++++++++++++++++++++++++++++++++++-------------------- tests/Makefile | 2 +- tests/mqtest.c | 46 ++++++++++++++++++++ ui.c | 66 +++++++++++++++-------------- ui.h | 5 +-- 8 files changed, 174 insertions(+), 81 deletions(-) create mode 100644 tests/mqtest.c (limited to 'main.c') diff --git a/.gitignore b/.gitignore index 4b8fd3a..3e2ffcd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /tests/producer /tests/consumer /tests/semtest +/tests/mqtest *.swp diff --git a/Makefile b/Makefile index fe89038..1abb87a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CFLAGS ?= $(shell ncurses5-config --cflags) -Wall -D_GNU_SOURCE=1 DBGFLAGS = -g -LDFLAGS ?= $(shell ncurses5-config --libs) -pthread +LDFLAGS ?= $(shell ncurses5-config --libs) -pthread -lrt CC ?= gcc INSTALL ?= install VERSION ?= $(shell if [ -d ./.git ]; then echo -n "git-"; git rev-parse --short HEAD; else echo "1.2a"; fi) diff --git a/config.h b/config.h index 26fdb3c..a559771 100644 --- a/config.h +++ b/config.h @@ -5,6 +5,10 @@ #define DEFAULT_FIFO "/lib/cryptsetup/passfifo" #define SHTDWN_CMD "echo 'o' >/proc/sysrq-trigger" +#define SEM_GUI "/naskpass-gui" +#define SEM_INP "/naskpass-input" +#define MSQ_PWD "/naskpass-passwd" + #ifdef _VERSION #define VERSION _VERSION #else diff --git a/main.c b/main.c index 670503e..c40265d 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "ui_ani.h" #include "ui_input.h" @@ -16,7 +19,9 @@ #include "config.h" -static bool ui_active = true; +static sem_t *sp_ui, *sp_input; +static mqd_t mq_passwd; + static void usage(char *arg0) @@ -51,23 +56,6 @@ check_fifo(char *fifo_path) return (false); } -/* stolen from http://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html */ -static int -input_timeout(int filedes, unsigned int seconds) -{ - fd_set set; - struct timeval timeout; - - /* Initialize the file descriptor set. */ - FD_ZERO (&set); - FD_SET (filedes, &set); - /* Initialize the timeout data structure. */ - timeout.tv_sec = seconds; - timeout.tv_usec = 0; - /* select returns 0 if timeout, 1 if input available, -1 if error. */ - return TEMP_FAILURE_RETRY(select(FD_SETSIZE, &set, NULL, NULL, &timeout)); -} - int run_cryptcreate(char *pass, char *crypt_cmd) { @@ -80,22 +68,65 @@ run_cryptcreate(char *pass, char *crypt_cmd) return (retval); } +void sigfunc(int signal) +{ + switch (signal) { + case SIGTERM: + case SIGKILL: + case SIGINT: + sem_trywait(sp_ui); + sem_trywait(sp_input); + break; + } +} + int main(int argc, char **argv) { - int ffd, c_status, opt; + int ret = EXIT_FAILURE, ffd = -1, c_status, opt, i_sval; pid_t child; char pbuf[MAX_PASSWD_LEN+1]; char *fifo_path = NULL; char *crypt_cmd = NULL; + struct timespec ts_sem_input; + struct mq_attr mq_attr; - memset(pbuf, '\0', MAX_PASSWD_LEN+1); + signal(SIGINT, sigfunc); + signal(SIGTERM, sigfunc); + signal(SIGKILL, sigfunc); + + if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) { + fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + if ( (sp_ui = sem_open(SEM_GUI, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED || + (sp_input = sem_open(SEM_INP, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED || +(mq_passwd = mq_open(MSQ_PWD, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, NULL)) == (mqd_t) -1 ) { + if ( errno == EEXIST ) { + fprintf(stderr, "%s: already started?\n", argv[0]); + } else { + fprintf(stderr, "%s: can not create semaphore: %d (%s)\n", argv[0], errno, strerror(errno)); + } + goto error; + } + if ( mq_getattr(mq_passwd, &mq_attr) == 0 ) { + mq_attr.mq_maxmsg = 2; + mq_attr.mq_msgsize = MAX_PASSWD_LEN; + if ( mq_setattr(mq_passwd, &mq_attr, NULL) != 0 ) { + fprintf(stderr, "%s: can not SET message queue attributes: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + } else { + fprintf(stderr, "%s: can not GET message queue attributes: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + memset(pbuf, '\0', MAX_PASSWD_LEN+1); while ((opt = getopt(argc, argv, "hf:c:")) != -1) { switch (opt) { case 'h': usage(argv[0]); - exit(EXIT_SUCCESS); + goto error; case 'f': fifo_path = strdup(optarg); break; @@ -104,56 +135,66 @@ main(int argc, char **argv) break; default: usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } } if (optind < argc) { fprintf(stderr, "%s: I dont understand you.\n\n", argv[0]); usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } if (fifo_path == NULL) fifo_path = strdup(DEFAULT_FIFO); if (check_fifo(fifo_path) == false) { usage(argv[0]); - exit(EXIT_FAILURE); + goto error; } if ((ffd = open(fifo_path, O_NONBLOCK | O_RDWR)) < 0) { - fprintf(stderr, "fifo: %s\n", fifo_path); - perror("open"); - exit(EXIT_FAILURE); + fprintf(stderr, "%s: fifo '%s' error: %d (%s)\n", argv[0], fifo_path, errno, strerror(errno)); + goto error; } if ((child = fork()) == 0) { /* child */ - ui_active = true; - do_ui(ffd); - ui_active = false; + fclose(stderr); + /* Slave process: TUI */ + sem_post(sp_ui); + do_ui(); } else if (child > 0) { /* parent */ fclose(stdin); - while (input_timeout(ffd, 1) == 0) { - usleep(100000); - if (ui_active == true) { - // TODO: smthng + fclose(stdout); + /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */ + while ( sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0 ) { + if ( sem_getvalue(sp_input, &i_sval) == 0 && i_sval > 0 ) { + if (read(ffd, pbuf, MAX_PASSWD_LEN) > 0) { + if (run_cryptcreate(pbuf, crypt_cmd) != 0) { + fprintf(stderr, "cryptcreate error\n"); + } + } + } else if ( mq_receive(mq_passwd, pbuf, MAX_PASSWD_LEN, NULL) > 0 ) { +exit(77); } + usleep(100000); } - stop_ui(); wait(&c_status); - if (read(ffd, pbuf, MAX_PASSWD_LEN) > 0) { - if (run_cryptcreate(pbuf, crypt_cmd) != 0) { - fprintf(stderr, "cryptcreate error\n"); - } - } memset(pbuf, '\0', MAX_PASSWD_LEN+1); } else { /* fork error */ perror("fork"); - exit(EXIT_FAILURE); + goto error; } - close(ffd); + ret = EXIT_SUCCESS; +error: + if (ffd >= 0) close(ffd); if (crypt_cmd != NULL) free(crypt_cmd); - free(fifo_path); - return (EXIT_SUCCESS); + if (fifo_path != NULL) free(fifo_path); + sem_close(sp_ui); + sem_close(sp_input); + mq_close(mq_passwd); + sem_unlink(SEM_GUI); + sem_unlink(SEM_INP); + mq_unlink(MSQ_PWD); + exit(ret); } diff --git a/tests/Makefile b/tests/Makefile index 22a5469..5a041e6 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,5 @@ CFLAGS = -Wall -LDFLAGS = -lpthread +LDFLAGS = -lpthread -lrt CC = gcc SOURCES = $(wildcard *.c) BINARIES = $(patsubst %.c,%,$(SOURCES)) diff --git a/tests/mqtest.c b/tests/mqtest.c new file mode 100644 index 0000000..56c2d2b --- /dev/null +++ b/tests/mqtest.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include + +#include + + +static mqd_t mq_test; +static const size_t bufsiz = 256; + +int main(int argc, char **argv) +{ + struct mq_attr m_attr; + char buf[bufsiz], recv[bufsiz]; + + memset(buf, '\0', bufsiz); + memset(buf, '\0', bufsiz); + if (argc > 1) + strncpy(buf, argv[1], bufsiz-1); + + mq_unlink("/testmq"); + assert( (mq_test = mq_open( "/testmq", O_CREAT | O_EXCL | O_RDWR | O_NONBLOCK, S_IRUSR | S_IWUSR, NULL )) != (mqd_t)-1 ); + assert( mq_getattr(mq_test, &m_attr) == 0 ); + printf("flags.....: %ld\n" + "maxmsg....: %ld\n" + "msgsize...: %ld\n" + "curmsg....: %ld\n", + m_attr.mq_flags, m_attr.mq_maxmsg, m_attr.mq_msgsize, m_attr.mq_curmsgs); + + m_attr.mq_msgsize = bufsiz-1; + assert ( mq_setattr(mq_test, &m_attr, NULL) == 0 ); + assert ( mq_send(mq_test, buf, bufsiz-1, 0) == 0 ); + assert ( mq_getattr(mq_test, &m_attr) == 0 ); + printf("new msgsize...: %ld\n" + "new curmsg....: %ld\n", + m_attr.mq_msgsize, m_attr.mq_curmsgs); + assert ( mq_receive(mq_test, recv, bufsiz-1, 0) > 0 ); + + printf("RECV: %s\n", recv); + + return 0; +} + diff --git a/ui.c b/ui.c index 58cc226..9d0abae 100644 --- a/ui.c +++ b/ui.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include #include "ui.h" @@ -30,17 +33,18 @@ #define STRLEN(s) (sizeof(s)/sizeof(s[0])) -static int ffd; static unsigned int max_x, max_y; static WINDOW *wnd_main; static struct nask_ui *nui = NULL; static pthread_t thrd; -static bool active, passwd_from_ui; +static bool active; static unsigned int atmout = APP_TIMEOUT; static pthread_cond_t cnd_update = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mtx_update = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mtx_busy = PTHREAD_MUTEX_INITIALIZER; static sem_t sem_rdy; +static sem_t *sp_ui, *sp_input; +static mqd_t mq_passwd; void @@ -183,7 +187,6 @@ static int run_ui_thrd(void) { pthread_mutex_lock(&mtx_busy); active = true; - passwd_from_ui = false; pthread_cond_signal(&cnd_update); pthread_mutex_unlock(&mtx_busy); return (pthread_create(&thrd, NULL, &ui_thrd, NULL)); @@ -205,15 +208,15 @@ stop_ui_thrd(void) } static int -send_passwd(int fifo_fd, char *passwd, size_t len) +mq_passwd_send(char *passwd, size_t len) { - if (write(fifo_fd, passwd, len) != len) { - memset(passwd, '\0', len); - return (errno); - } else { - memset(passwd, '\0', len); - return (0); + struct mq_attr m_attr; + + if (mq_send(mq_passwd, "hellomq", 7, 0) == 0 && mq_getattr(mq_passwd, &m_attr) == 0) { + return m_attr.mq_curmsgs; } + memset(passwd, '\0', len); + return -1; } static bool @@ -224,9 +227,9 @@ process_key(char key, struct input *a, WINDOW *win) atmout = APP_TIMEOUT; switch (key) { case UIKEY_ENTER: - send_passwd(ffd, a->input, a->input_len); - passwd_from_ui = true; - retval = false; + if ( mq_passwd_send(a->input, a->input_len) > 0 ) { + retval = false; + } else retval = true; break; case UIKEY_BACKSPACE: del_input(win, a); @@ -262,18 +265,21 @@ infownd_update(WINDOW *win, struct txtwindow *tw) } int -do_ui(int fifo_fd) +do_ui(void) { struct input *pw_input; struct anic *heartbeat; struct statusbar *higher, *lower; struct txtwindow *infownd; char key = '\0'; - char *title; + char *title = NULL; + int i_sval = -1, ret = DOUI_ERR; asprintf(&title, "/* %s-%s */", PKGNAME, VERSION); - ffd = fifo_fd; - if (sem_init(&sem_rdy, 0, 0) == -1) { + sp_ui = sem_open(SEM_GUI, 0, 0, 0); + sp_input = sem_open(SEM_INP, 0, 0, 0); + mq_passwd = mq_open(MSQ_PWD, O_WRONLY, S_IWUSR, NULL); + if ( sem_init(&sem_rdy, 0, 0) == -1 || !sp_ui || !sp_input || mq_passwd == (mqd_t)-1 ) { perror("init semaphore"); goto error; } @@ -295,7 +301,7 @@ do_ui(int fifo_fd) } sem_wait(&sem_rdy); wtimeout(wnd_main, 1000); - while (active == true) { + while ( active && sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0 ) { if ((key = wgetch(wnd_main)) == '\0') { break; } @@ -308,6 +314,7 @@ do_ui(int fifo_fd) do_ui_update(false); pthread_mutex_unlock(&mtx_busy); } + ui_thrd_force_update(); stop_ui_thrd(); unregister_ui_elt(lower); unregister_ui_elt(higher); @@ -319,19 +326,16 @@ do_ui(int fifo_fd) free_statusbar(lower); free_txtwindow(infownd); free_ui(); - return (DOUI_OK); + ret = DOUI_OK; + sem_trywait(sp_ui); + mq_close(mq_passwd); error: - free(title); - return (DOUI_ERR); -} - -bool -is_passwd_from_ui(void) -{ - bool ret; - pthread_mutex_lock(&mtx_busy); - ret = passwd_from_ui; - pthread_mutex_unlock(&mtx_busy); - return (ret); + if (title) free(title); + if (sp_ui) sem_close(sp_ui); + if (sp_input) sem_close(sp_input); + title = NULL; + sp_ui = NULL; + sp_input = NULL; + return ret; } diff --git a/ui.h b/ui.h index 77a5bc9..a34ca10 100644 --- a/ui.h +++ b/ui.h @@ -52,12 +52,9 @@ void free_ui(void); int -do_ui(int fifo_fd); +do_ui(void); void stop_ui(void); -bool -is_passwd_from_ui(void); - #endif -- cgit v1.2.3 From 1c8d37efdba437ab42d3d14257b7eb6adf7f2e4f Mon Sep 17 00:00:00 2001 From: toni Date: Mon, 26 Oct 2015 00:30:52 +0100 Subject: exported UI IPC --- .gitignore | 3 + Makefile | 8 ++- config.h | 1 + main.c | 81 +++++++-------------- tests/Makefile | 5 ++ tests/semconfig.h | 1 + tests/semtest.c | 8 ++- tests/semtest2.c | 43 +++++++++++ ui.c | 209 ++++++++++++++++++++++++++++-------------------------- ui.h | 19 ++++- ui_elements.c | 62 +++++++++++++++- ui_elements.h | 7 -- ui_input.c | 13 +++- ui_input.h | 6 +- ui_ipc.c | 139 ++++++++++++++++++++++++++++++++++++ ui_ipc.h | 52 ++++++++++++++ 16 files changed, 482 insertions(+), 175 deletions(-) create mode 100644 tests/semtest2.c create mode 100644 ui_ipc.c create mode 100644 ui_ipc.h (limited to 'main.c') diff --git a/.gitignore b/.gitignore index d965c57..dc4c5e9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,10 @@ /tests/producer /tests/consumer /tests/semtest +/tests/semtest2 /tests/mqtest /tests/strsep *.swp *.o +*.d + diff --git a/Makefile b/Makefile index 2780c74..1e581c9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS = $(shell ncurses5-config --cflags) -Wall -D_GNU_SOURCE=1 -fPIC +CFLAGS = $(shell ncurses5-config --cflags) -Wall -Wundef -Wshadow -D_GNU_SOURCE=1 -fPIC -fomit-frame-pointer -fno-inline -fstrength-reduce -frerun-cse-after-loop -frerun-loop-opt -fexpensive-optimizations -fstrict-aliasing -Os -MD -MP DBGFLAGS = -g LDFLAGS = $(shell ncurses5-config --libs) -pthread -lrt CC = gcc @@ -6,8 +6,9 @@ INSTALL = install STRIP = strip VERSION = $(shell if [ -d ./.git ]; then echo -n "git-"; git rev-parse --short HEAD; else echo "1.2a"; fi) BIN = naskpass -SOURCES = status.c ui_ani.c ui_input.c ui_statusbar.c ui_nwindow.c ui.c ui_elements.c main.c +SOURCES = status.c ui_ani.c ui_input.c ui_statusbar.c ui_nwindow.c ui.c ui_elements.c ui_ipc.c main.c OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) +DEPS = $(patsubst %.c,%.d,$(SOURCES)) all: $(OBJECTS) $(BIN) @@ -18,7 +19,7 @@ $(BIN): $(SOURCES) $(CC) $(LDFLAGS) $(OBJECTS) -o $(BIN) $(MAKE) -C tests CC='$(CC)' CFLAGS='$(CFLAGS)' all -strip: +strip: $(OBJECTS) $(BIN) $(STRIP) $(BIN) release: all strip @@ -41,6 +42,7 @@ uninstall: rmdir --ignore-fail-on-non-empty $(DESTDIR)/usr/share/naskpass clean: + rm -f $(DEPS) rm -f $(OBJECTS) rm -f $(BIN) $(MAKE) -C tests clean diff --git a/config.h b/config.h index 4f39307..a7fddc0 100644 --- a/config.h +++ b/config.h @@ -8,6 +8,7 @@ #define SEM_GUI "/naskpass-gui" #define SEM_INP "/naskpass-input" #define SEM_BSY "/naskpass-busy" +#define SEM_RDY "/naskpass-initialized" #define MSQ_PWD "/naskpass-passwd" #define MSQ_INF "/naskpass-info" diff --git a/main.c b/main.c index 6bcfb00..58c4baf 100644 --- a/main.c +++ b/main.c @@ -12,29 +12,32 @@ #include #include +#include "config.h" + +#include "ui.h" +#include "ui_ipc.h" #include "ui_ani.h" #include "ui_input.h" #include "ui_statusbar.h" -#include "ui.h" -#include "config.h" #define MSG(msg_idx) msg_arr[msg_idx] -static sem_t *sp_ui, *sp_input, *sp_busy; -static mqd_t mq_passwd, mq_info; - enum msg_index { MSG_BUSY_FD = 0, - MSG_BUSY + MSG_BUSY, + MSG_NO_FIFO, + MSG_FIFO_ERR, + MSG_NUM }; -static const char *msg_arr[] = { "Please wait, got a piped password ..", "Please wait, busy .." }; +static const char *msg_arr[] = { "Please wait, got a piped password ..", "Please wait, busy ..", + "check_fifo: %s is not a FIFO\n", "check_fifo: %s error(%d): %s\n" }; static void usage(char *arg0) { - fprintf(stderr, "%s (%s)\n %s\n", PKGNAME, VERSION, PKGDESC); + fprintf(stderr, "\n%s (%s)\n %s\n", PKGNAME, VERSION, PKGDESC); fprintf(stderr, " Written by %s (%s).\n", AUTHOR, AUTHOR_EMAIL); fprintf(stderr, " License GPLv3+: GNU GPL version 3 or later .\n\n"); fprintf(stderr, " Command:\n\t%s [args]\n", arg0); @@ -54,13 +57,13 @@ check_fifo(char *fifo_path) if (S_ISFIFO(st.st_mode) == 1) { return (true); } else { - fprintf(stderr, "stat: %s is not a FIFO\n", fifo_path); + fprintf(stderr, MSG(MSG_NO_FIFO), fifo_path); return (false); } } } } - perror("check_fifo"); + fprintf(stderr, MSG(MSG_FIFO_ERR), fifo_path, errno, strerror(errno)); return (false); } @@ -81,11 +84,9 @@ void sigfunc(int signal) { switch (signal) { case SIGTERM: - case SIGKILL: case SIGINT: - sem_trywait(sp_ui); - sem_trywait(sp_input); - sem_trywait(sp_busy); + ui_ipc_semtrywait(SEM_UI); + ui_ipc_semtrywait(SEM_IN); break; } } @@ -93,42 +94,23 @@ void sigfunc(int signal) int main(int argc, char **argv) { - int ret = EXIT_FAILURE, ffd = -1, c_status, opt, i_sval; + int ret = EXIT_FAILURE, ffd = -1, c_status, opt; pid_t child; char pbuf[IPC_MQSIZ+1]; char *fifo_path = NULL; char *crypt_cmd = NULL; struct timespec ts_sem_input; - struct mq_attr mq_attr; signal(SIGINT, sigfunc); signal(SIGTERM, sigfunc); - signal(SIGKILL, sigfunc); - - mq_attr.mq_flags = 0; - mq_attr.mq_msgsize = IPC_MQSIZ; - mq_attr.mq_maxmsg = 3; - mq_attr.mq_curmsgs = 0; if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) { fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno)); goto error; } - sp_ui = sem_open(SEM_GUI, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0); - sp_input = sem_open(SEM_INP, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0); - sp_busy = sem_open(SEM_BSY, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0); - mq_passwd = mq_open(MSQ_PWD, O_NONBLOCK | O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG, &mq_attr); - mq_info = mq_open(MSQ_INF, O_NONBLOCK | O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG, &mq_attr); - - if ( sp_ui == SEM_FAILED || sp_input == SEM_FAILED || sp_busy == SEM_FAILED || - mq_passwd == (mqd_t) -1 || mq_info == (mqd_t) -1 ) { - - if ( errno == EEXIST ) { - fprintf(stderr, "%s: already started?\n", argv[0]); - } else { - fprintf(stderr, "%s: can not create semaphore/message queue: %d (%s)\n", argv[0], errno, strerror(errno)); - } + if (ui_ipc_init(1) != 0) { + fprintf(stderr, "%s: can not create semaphore/message queue: %d (%s)\n", argv[0], errno, strerror(errno)); goto error; } @@ -165,7 +147,7 @@ main(int argc, char **argv) goto error; } - sem_post(sp_ui); + ui_ipc_sempost(SEM_UI); if ((child = fork()) == 0) { /* child */ fclose(stderr); @@ -176,20 +158,20 @@ main(int argc, char **argv) fclose(stdin); fclose(stdout); /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */ - while ( (sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0) || (sem_getvalue(sp_input, &i_sval) == 0 && i_sval > 0) ) { + while ( ui_ipc_getvalue(SEM_UI) > 0 || ui_ipc_getvalue(SEM_IN) > 0 ) { if (read(ffd, pbuf, IPC_MQSIZ) >= 0) { - sem_post(sp_busy); - mq_send(mq_info, MSG(MSG_BUSY_FD), strlen(MSG(MSG_BUSY_FD)), 0); + ui_ipc_sempost(SEM_BS); + ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY_FD), strlen(MSG(MSG_BUSY_FD))); if (run_cryptcreate(pbuf, crypt_cmd) != 0) { fprintf(stderr, "cryptcreate error\n"); } - } else if ( mq_receive(mq_passwd, pbuf, IPC_MQSIZ, NULL) >= 0 ) { - sem_post(sp_busy); - mq_send(mq_info, MSG(MSG_BUSY), strlen(MSG(MSG_BUSY)), 0); + } else if ( ui_ipc_msgrecv(MQ_PW, pbuf, IPC_MQSIZ) > 0 ) { + ui_ipc_sempost(SEM_BS); + ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY), strlen(MSG(MSG_BUSY))); if (run_cryptcreate(pbuf, crypt_cmd) != 0) { fprintf(stderr, "cryptcreate error\n"); } - sem_wait(sp_input); + ui_ipc_semwait(SEM_IN); } usleep(100000); } @@ -206,15 +188,6 @@ error: if (ffd >= 0) close(ffd); if (crypt_cmd != NULL) free(crypt_cmd); if (fifo_path != NULL) free(fifo_path); - sem_close(sp_ui); - sem_close(sp_input); - sem_close(sp_busy); - mq_close(mq_passwd); - mq_close(mq_info); - sem_unlink(SEM_GUI); - sem_unlink(SEM_INP); - sem_unlink(SEM_BSY); - mq_unlink(MSQ_PWD); - mq_unlink(MSQ_INF); + ui_ipc_free(1); exit(ret); } diff --git a/tests/Makefile b/tests/Makefile index 5a041e6..436d00f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,13 +3,18 @@ LDFLAGS = -lpthread -lrt CC = gcc SOURCES = $(wildcard *.c) BINARIES = $(patsubst %.c,%,$(SOURCES)) +DEPS = $(patsubst %.c,%.d,$(SOURCES)) all: $(BINARIES) +semtest2: + $(CC) $(CFLAGS) $(LDFLAGS) ../ui_ipc.o semtest2.c -o semtest2 + %: %.c $(CC) $(CFLAGS) $(LDFLAGS) $< -o $(patsubst %.c,%,$<) clean: + rm -f $(DEPS) rm -f $(BINARIES) .PHONY: all install clean diff --git a/tests/semconfig.h b/tests/semconfig.h index e34984d..0ad08b3 100644 --- a/tests/semconfig.h +++ b/tests/semconfig.h @@ -2,6 +2,7 @@ #define CONFIG_H 1 #define LOG(text) fprintf(stderr, "%s\n", text); +#define CMD(cmd) LOG(cmd); cmd; #define TESTSEM "/testsem" #define CNTSEM "/testcnt" diff --git a/tests/semtest.c b/tests/semtest.c index 7968127..f462a6e 100644 --- a/tests/semtest.c +++ b/tests/semtest.c @@ -7,15 +7,16 @@ #include #include +#include "semconfig.h" + sem_t *mysem = NULL; pid_t child; -#define LOG(cmd) fprintf(stderr, "%s\n", cmd); int main(int argc, char **argv) { - sem_unlink("/mysem"); - if ( (mysem = sem_open("/mysem", O_CREAT, S_IRUSR | S_IWUSR, 1)) != NULL ) { + sem_unlink(TESTSEM); + if ( (mysem = sem_open(TESTSEM, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) != NULL ) { if ( (child = fork()) == 0 ) { /* child */ sleep(1); @@ -37,6 +38,7 @@ int main(int argc, char **argv) { sem_close(mysem); exit(1); } + sem_unlink(TESTSEM); exit(0); } diff --git a/tests/semtest2.c b/tests/semtest2.c new file mode 100644 index 0000000..c015df8 --- /dev/null +++ b/tests/semtest2.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../ui_ipc.h" + +pid_t child; + +#define LOG(cmd) fprintf(stderr, "%s\n", cmd); + +int main(int argc, char **argv) { + if (ui_ipc_init(1) != 0) { + perror("ui_ipc_init"); + exit(1); + } + if ( (child = fork()) == 0 ) { + /* child */ + sleep(1); + LOG("child: sempost"); + ui_ipc_sempost(SEM_RD); + LOG("child: done"); + sleep(1); + exit(0); + } else if (child > 0) { + /* parent */ + LOG("parent: semwait"); + ui_ipc_semwait(SEM_RD); + LOG("parent: waitpid"); + waitpid(child, NULL, 0); + } else if (child < 0) { + perror("fork"); + exit(1); + } + ui_ipc_free(1); + + exit(0); +} + diff --git a/ui.c b/ui.c index e5f4454..dc16b96 100644 --- a/ui.c +++ b/ui.c @@ -15,6 +15,7 @@ #include #include "ui.h" +#include "ui_ipc.h" #include "ui_elements.h" #include "ui_ani.h" #include "ui_input.h" @@ -40,52 +41,83 @@ static unsigned int max_x, max_y; static WINDOW *wnd_main; -static struct nask_ui *nui = NULL; -static struct nask_input *nin = NULL; +static struct nask_ui /* simple linked list to all GUI objects */ *nui = NULL, + /* simple linked list to all INPUT objects */ *nin = NULL, /* current active input */ *active = NULL; static pthread_t thrd; static unsigned int atmout = APP_TIMEOUT; static pthread_cond_t cnd_update = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mtx_update = PTHREAD_MUTEX_INITIALIZER; -static sem_t sem_rdy; -static sem_t /* TUI active? */ *sp_ui, /* Textfield input available? */ *sp_input; -static mqd_t mq_passwd, mq_info; -void -register_ui_elt(ui_callback uicb, void *data, WINDOW *wnd) +static void +register_basic(enum ui_type utype, union ui_data uicb, void *data, WINDOW *wnd) { - struct nask_ui *tmp, *new; + struct nask_ui *tmp, *new, *ui = NULL; - if (nui != NULL) { - tmp = nui; - while (tmp->next != NULL) { - tmp = tmp->next; - } + switch (utype) { + case UI_ELEMENT: + ui = nui; + break; + case UI_INPUT: + ui = nin; + break; } new = calloc(1, sizeof(struct nask_ui)); - new->ui_elt_cb = uicb; + new->type = utype; + new->callback = uicb; new->wnd = wnd; new->data = data; new->next = NULL; - if (nui == NULL) { - nui = new; - nui->next = NULL; + if (ui == NULL) { + ui = new; + ui->next = NULL; + switch (utype) { + case UI_ELEMENT: + nui = ui; + break; + case UI_INPUT: + nin = ui; + break; + } } else { + tmp = ui; + while (tmp->next != NULL) { + tmp = tmp->next; + } tmp->next = new; } } void -register_input(ui_input_callback ipcb, void *data, WINDOW *wnd) +register_ui_elt(ui_callback uicb, void *data, WINDOW *wnd) { - + union ui_data cb; + cb.ui_element = uicb; + register_basic(UI_ELEMENT, cb, data, wnd); } void -unregister_ui_elt(void *data) +register_ui_input(ui_input_callback ipcb, void *data, WINDOW *wnd) +{ + union ui_data cb; + cb.ui_input = ipcb; + register_basic(UI_INPUT, cb, data, wnd); +} + +static void +unregister_basic(enum ui_type utype, void *data) { - struct nask_ui *cur = nui, *next, *before = NULL; + struct nask_ui *cur, *next, *before = NULL, **ui = NULL; + switch (utype) { + case UI_ELEMENT: + ui = &nui; + break; + case UI_INPUT: + ui = &nin; + break; + } + cur = *ui; while (cur != NULL) { next = cur->next; if (cur->data != NULL && cur->data == data) { @@ -93,7 +125,7 @@ unregister_ui_elt(void *data) if (before != NULL) { before->next = next; } else { - nui = next; + *ui = next; } } before = cur; @@ -101,6 +133,46 @@ unregister_ui_elt(void *data) } } +void +unregister_ui_elt(void *data) +{ + unregister_basic(UI_ELEMENT, data); +} + +void +unregister_ui_input(void *data) +{ + unregister_basic(UI_INPUT, data); +} + +int +activate_ui_input(void *data) +{ + struct nask_ui *cur = nin; + + if (cur == NULL || data == NULL) return DOUI_NINIT; + while ( cur != NULL ) { + if ( cur == data && cur->type == UI_INPUT ) { + if ( cur->callback.ui_input(cur->wnd, data, UIKEY_ACTIVATE) == DOUI_OK ) { + active = cur; + return DOUI_OK; + } + } + cur = cur->next; + } + return DOUI_ERR; +} + +static bool +process_key(char key) +{ + atmout = APP_TIMEOUT; + if ( active != NULL ) { + return ( active->callback.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false ); + } + return false; +} + static int do_ui_update(bool timed_out) { @@ -112,8 +184,8 @@ do_ui_update(bool timed_out) /* call all draw callback's */ erase(); while (cur != NULL) { - if (cur->ui_elt_cb != NULL) { - cur->ui_elt_cb(cur->wnd, cur->data, timed_out); + if (cur->type == UI_ELEMENT && cur->callback.ui_element != NULL) { + cur->callback.ui_element(cur->wnd, cur->data, timed_out); doupdate(); } else { retval = UICB_ERR_CB; @@ -133,7 +205,7 @@ do_ui_update(bool timed_out) static void * ui_thrd(void *arg) { - int cnd_ret, i_sval; + int cnd_ret; struct timeval now; struct timespec wait; @@ -141,11 +213,11 @@ ui_thrd(void *arg) wait.tv_sec = now.tv_sec + UILOOP_TIMEOUT; wait.tv_nsec = now.tv_usec * 1000; do_ui_update(true); - sem_post(&sem_rdy); - while ( sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0 ) { + ui_ipc_sempost(SEM_RD); + while ( ui_ipc_getvalue(SEM_UI) > 0 ) { pthread_mutex_lock(&mtx_update); cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &wait); - if (--atmout == 0) sem_trywait(sp_ui); + if (--atmout == 0) ui_ipc_semtrywait(SEM_UI); do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) ); if (cnd_ret == ETIMEDOUT) { wait.tv_sec += UILOOP_TIMEOUT; @@ -202,66 +274,14 @@ stop_ui_thrd(void) return (pthread_join(thrd, NULL)); } -static int -mq_passwd_send(char *passwd, size_t len) -{ - struct mq_attr m_attr; - - sem_post(sp_input); - if (mq_send(mq_passwd, passwd, len, 0) == 0 && mq_getattr(mq_passwd, &m_attr) == 0) { - return m_attr.mq_curmsgs; - } - memset(passwd, '\0', len); - return -1; -} - -static bool -process_key(char key, struct input *a, WINDOW *win) -{ - bool retval = true; - - atmout = APP_TIMEOUT; - switch (key) { - case UIKEY_ENTER: - if ( mq_passwd_send(a->input, a->input_len) > 0 ) { - retval = false; - } else retval = true; - break; - case UIKEY_BACKSPACE: - del_input(win, a); - break; - case UIKEY_ESC: - retval = false; - break; - case UIKEY_DOWN: - case UIKEY_UP: - case UIKEY_LEFT: - case UIKEY_RIGHT: - break; - default: - add_input(win, a, key); - } - return (retval); -} - int do_ui(void) { - struct anic *heartbeat; char key = '\0'; - char *title = NULL, mq_msg[IPC_MQSIZ+1]; - int i_sval = -1, ret = DOUI_ERR; + char *title = NULL; + int ret = DOUI_ERR; asprintf(&title, "/* %s-%s */", PKGNAME, VERSION); - sp_ui = sem_open(SEM_GUI, 0, 0, 0); - sp_input = sem_open(SEM_INP, 0, 0, 0); - mq_passwd = mq_open(MSQ_PWD, O_WRONLY, 0, NULL); - mq_info = mq_open(MSQ_INF, O_RDONLY, 0, NULL); - if ( sem_init(&sem_rdy, 0, 0) == -1 || !sp_ui || !sp_input || mq_passwd == (mqd_t)-1 || mq_info == (mqd_t)-1 ) { - perror("init semaphore/messageq"); - goto error; - } - /* init TUI and UI Elements (input field, status bar, etc) */ init_ui(); init_ui_elements(wnd_main, max_x, max_y); @@ -269,25 +289,20 @@ do_ui(void) if (run_ui_thrd() != 0) { goto error; } - sem_wait(&sem_rdy); - wtimeout(wnd_main, 1000); - while ( sem_getvalue(sp_ui, &i_sval) == 0 && i_sval > 0 ) { + ui_ipc_semwait(SEM_RD); + wtimeout(wnd_main, 10); + while ( ui_ipc_getvalue(SEM_UI) > 0 ) { if ((key = wgetch(wnd_main)) == '\0') { break; } if (key == -1) { continue; } - if ( process_key(key, pw_input, wnd_main) == false ) { - curs_set(0); - memset(mq_msg, '\0', IPC_MQSIZ+1); - mq_receive(mq_info, mq_msg, IPC_MQSIZ+1, 0); - set_txtwindow_text(infownd, mq_msg); - set_txtwindow_active(infownd, true); - sleep(3); - sem_trywait(sp_ui); + if ( process_key(key) != true ) { +printf("BLABL\n"); + break; } - activate_input(wnd_main, pw_input); +printf("BLUBB\n"); do_ui_update(false); } ui_thrd_force_update(); @@ -295,15 +310,9 @@ do_ui(void) free_ui_elements(); ret = DOUI_OK; - mq_close(mq_passwd); - mq_close(mq_info); error: if (title) free(title); - if (sp_ui) sem_close(sp_ui); - if (sp_input) sem_close(sp_input); title = NULL; - sp_ui = NULL; - sp_input = NULL; return ret; } diff --git a/ui.h b/ui.h index dc19fab..d5a9123 100644 --- a/ui.h +++ b/ui.h @@ -12,10 +12,11 @@ #define DOUI_OK 0 #define DOUI_ERR 1 #define DOUI_TMOUT 2 -#define DOUI_PASSWD 3 +#define DOUI_NINIT 3 #define UILOOP_TIMEOUT 1 +#define UIKEY_ACTIVATE 0 #define UIKEY_ENTER 10 #define UIKEY_BACKSPACE 7 #define UIKEY_ESC 27 @@ -29,13 +30,19 @@ typedef int (*ui_callback)(WINDOW *, void *, bool); typedef int (*ui_input_callback)(WINDOW *, void *, int); -union ui_type { +enum ui_type { + UI_ELEMENT, + UI_INPUT +}; + +union ui_data { ui_callback ui_element; ui_input_callback ui_input; }; struct nask_ui { - union ui_type type; + enum ui_type type; + union ui_data callback; WINDOW *wnd; void *data; struct nask_ui *next; @@ -50,6 +57,12 @@ register_ui_input(ui_input_callback ipcb, void *data, WINDOW *wnd); void unregister_ui_elt(void *data); +void +unregister_ui_input(void *data); + +int +activate_ui_input(void *data); + void ui_thrd_force_update(void); diff --git a/ui_elements.c b/ui_elements.c index b5b56e2..b9885a0 100644 --- a/ui_elements.c +++ b/ui_elements.c @@ -2,8 +2,15 @@ #include #include +#include "ui.h" +#include "ui_ipc.h" +#include "ui_ani.h" +#include "ui_input.h" +#include "ui_statusbar.h" +#include "ui_nwindow.h" #include "ui_elements.h" +#include "status.h" #define PASSWD_WIDTH 35 #define PASSWD_HEIGHT 5 @@ -44,6 +51,57 @@ infownd_update(WINDOW *win, struct txtwindow *tw) return (0); } +static int +mq_passwd_send(char *passwd, size_t len) +{ + int ret; + + ui_ipc_sempost(SEM_IN); + ret = ui_ipc_msgsend(MQ_PW, passwd, len); + memset(passwd, '\0', len); + return ret; +} + +static int +passwd_input_cb(WINDOW *wnd, void *data, int key) +{ + struct input *a = (struct input *) data; + +/* + * if ( process_key(key, pw_input, wnd_main) == false ) { + * curs_set(0); + * memset(mq_msg, '\0', IPC_MQSIZ+1); + * mq_receive(mq_info, mq_msg, IPC_MQSIZ+1, 0); + * set_txtwindow_text(infownd, mq_msg); + * set_txtwindow_active(infownd, true); + * sleep(3); + * sem_trywait(sp_ui); + * } + * activate_input(wnd_main, pw_input); + */ + switch (key) { + case UIKEY_ENTER: + if ( mq_passwd_send(a->input, a->input_len) > 0 ) { + return DOUI_OK; + } else return DOUI_ERR; + break; + case UIKEY_BACKSPACE: + del_input(wnd, a); + break; + case UIKEY_ESC: + return DOUI_ERR; + break; + case UIKEY_DOWN: + case UIKEY_UP: + case UIKEY_LEFT: + case UIKEY_RIGHT: + break; + default: + add_input(wnd, a, key); + } + return DOUI_OK; +} + void init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y) { @@ -56,7 +114,7 @@ init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y) infownd->userptr = calloc(4, sizeof(char)); (*(char*)(infownd->userptr)) = '.'; - register_input(NULL, pw_input); + register_input(NULL, pw_input, passwd_input_cb); register_statusbar(higher); register_statusbar(lower); register_anic(heartbeat); @@ -72,7 +130,7 @@ free_ui_elements(void) unregister_ui_elt(lower); unregister_ui_elt(higher); unregister_ui_elt(heartbeat); - unregister_ui_elt(pw_input); + unregister_input(pw_input); free_input(pw_input); free_anic(heartbeat); free_statusbar(higher); diff --git a/ui_elements.h b/ui_elements.h index 591e18b..0cf8826 100644 --- a/ui_elements.h +++ b/ui_elements.h @@ -1,13 +1,6 @@ #ifndef UI_ELEMENTS_H #define UI_ELEMENTS_H 1 -#include "ui.h" -#include "ui_ani.h" -#include "ui_input.h" -#include "ui_statusbar.h" -#include "ui_nwindow.h" - -#include "status.h" #include "config.h" diff --git a/ui_input.c b/ui_input.c index 63d8bee..43836f1 100644 --- a/ui_input.c +++ b/ui_input.c @@ -125,7 +125,7 @@ activate_input(WINDOW *win, struct input *a) } else { wmove(win, a->y, a->x + p_len + a->cur_pos); } - return (UICB_OK); + return (activate_ui_input( (void *) a )); } int @@ -174,7 +174,16 @@ input_cb(WINDOW *win, void *data, bool timed_out) } void -register_input(WINDOW *win, struct input *a) +register_input(WINDOW *win, struct input *a, ui_input_callback uin) { + a->cb_input = uin; register_ui_elt(input_cb, (void *) a, win); + register_ui_input(uin, (void *) a, win); +} + +void +unregister_input(struct input *a) +{ + unregister_ui_input( (void *) a ); + unregister_ui_elt( (void *) a ); } diff --git a/ui_input.h b/ui_input.h index e65d560..be93864 100644 --- a/ui_input.h +++ b/ui_input.h @@ -16,6 +16,7 @@ struct input { char *prompt; chtype attrs; chtype shadow; + ui_input_callback cb_input; }; struct input * @@ -37,6 +38,9 @@ int input_cb(WINDOW *win, void *data, bool timed_out); void -register_input(WINDOW *win, struct input *a); +register_input(WINDOW *win, struct input *a, ui_input_callback uin); + +void +unregister_input(struct input *a); #endif diff --git a/ui_ipc.c b/ui_ipc.c new file mode 100644 index 0000000..60da7cb --- /dev/null +++ b/ui_ipc.c @@ -0,0 +1,139 @@ +#include +#include +#include +#ifdef SEM_TIMEDWAIT +#include +#endif +#include +#include +#include +#include + +#include "ui_ipc.h" + +#define JMP_IF(cmd, retval, jmplabel) if ( (cmd) == retval ) { printf("(%s) == %p\n", #cmd, (void*)retval); goto jmplabel; } + + +static sem_t *sems[SEM_NUM]; +static mqd_t msqs[MSQ_NUM]; +static unsigned char initialized = 0; + + +int +ui_ipc_init(int is_master) +{ + volatile int sp_oflags, mq_oflags; + mode_t crt_flags; + struct mq_attr m_attr; + + if (initialized) { + return -1; + } + bzero(sems, sizeof(sem_t*)*SEM_NUM); + bzero(msqs, sizeof(mqd_t)*MSQ_NUM); + m_attr.mq_flags = 0; + m_attr.mq_msgsize = IPC_MQSIZ; + m_attr.mq_maxmsg = 3; + m_attr.mq_curmsgs = 0; + if (is_master) { + sp_oflags = O_CREAT | O_EXCL; + mq_oflags = O_NONBLOCK | O_CREAT | O_EXCL; + crt_flags = S_IRUSR | S_IWUSR; + JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + } else { + sp_oflags = 0; + mq_oflags = 0; + crt_flags = 0; + JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + } + JMP_IF( sems[SEM_UI] = sem_open(SEM_GUI, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_IN] = sem_open(SEM_INP, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_BS] = sem_open(SEM_BSY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_RD] = sem_open(SEM_RDY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + initialized = 1; + return 0; +error: + return errno; +} + +void +ui_ipc_free(int is_master) +{ + int i; + + if (!initialized) { + return; + } + for (i = 0; i < SEM_NUM; i++) { + if (sems[i]) sem_close(sems[i]); + } + for (i = 0; i < MSQ_NUM; i++) { + if (msqs[i]) mq_close(msqs[i]); + } + if (is_master > 0) { + sem_unlink(SEM_BSY); + sem_unlink(SEM_GUI); + sem_unlink(SEM_INP); + sem_unlink(SEM_RDY); + mq_unlink(MSQ_PWD); + mq_unlink(MSQ_INF); + } + initialized = 0; +} + +int +ui_ipc_sempost(enum UI_IPC_SEM e_sp) +{ + return ( sem_post(sems[e_sp]) ); +} + +int +ui_ipc_semwait(enum UI_IPC_SEM e_sp) +{ + return ( sem_wait(sems[e_sp]) ); +} + +int +ui_ipc_semtrywait(enum UI_IPC_SEM e_sp) +{ + return ( sem_trywait(sems[e_sp]) ); +} + +int +ui_ipc_getvalue(enum UI_IPC_SEM e_sp) +{ + int sp_val = 0; + + if (sem_getvalue(sems[e_sp], &sp_val) != 0) { + return -1; + } + return sp_val; +} + +#ifdef SEM_TIMEDWAIT +int +ui_ipc_semtimedwait(enum UI_IPC_SEM e_sp, int timeout) +{ + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + return -1; + } + ts.tc_sec += timeout; + return ( sem_timedwait(sems[q_mq], &ts) ); +} +#endif + +int +ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len) +{ + return ( mq_send(msqs[e_mq], msg_ptr, msg_len, 0) ); +} + +ssize_t +ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len) +{ + return ( mq_receive(msqs[e_mq], msg_ptr, msg_len, NULL) ); +} + diff --git a/ui_ipc.h b/ui_ipc.h new file mode 100644 index 0000000..2c5bcb5 --- /dev/null +++ b/ui_ipc.h @@ -0,0 +1,52 @@ +#ifndef UI_IPC_H +#define UI_IPC_H 1 + +#include "status.h" +#include "config.h" + + +enum UI_IPC_SEM { + SEM_RD = 0, /* UI Init done? */ + SEM_UI, /* TUI active? */ + SEM_IN, /* Textfield has input avail */ + SEM_BS, /* Master process busy */ + SEM_NUM +}; + +enum UI_IPC_MSQ { + MQ_PW = 0, + MQ_IF, + MSQ_NUM +}; + + +int +ui_ipc_init(int is_master); + +void +ui_ipc_free(int is_master); + +int +ui_ipc_sempost(enum UI_IPC_SEM e_sp); + +int +ui_ipc_semwait(enum UI_IPC_SEM e_sp); + +int +ui_ipc_semtrywait(enum UI_IPC_SEM e_sp); + +int +ui_ipc_getvalue(enum UI_IPC_SEM e_sp); + +#ifdef SEM_TIMEDWAIT +int +ui_ipc_semtimedwait(enum UI_IPC_MSQ e_sp, int timeout); +#endif + +int +ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len); + +ssize_t +ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len); + +#endif -- cgit v1.2.3 From 295ca9cb2bd2ebf58e9904a75312e3d17904bb51 Mon Sep 17 00:00:00 2001 From: toni Date: Tue, 3 Nov 2015 00:14:06 +0100 Subject: some MV(C) stuff --- main.c | 4 ++++ ui.c | 5 ++--- ui.h | 7 +------ ui_elements.c | 3 ++- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 58c4baf..721be77 100644 --- a/main.c +++ b/main.c @@ -150,9 +150,13 @@ main(int argc, char **argv) ui_ipc_sempost(SEM_UI); if ((child = fork()) == 0) { /* child */ + if (ffd >= 0) close(ffd); + if (crypt_cmd != NULL) free(crypt_cmd); + if (fifo_path != NULL) free(fifo_path); fclose(stderr); /* Slave process: TUI */ do_ui(); + exit(0); } else if (child > 0) { /* parent */ fclose(stdin); diff --git a/ui.c b/ui.c index dc16b96..15d55e4 100644 --- a/ui.c +++ b/ui.c @@ -168,6 +168,7 @@ process_key(char key) { atmout = APP_TIMEOUT; if ( active != NULL ) { +printf("XXXXXXXX\n"); return ( active->callback.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false ); } return false; @@ -299,10 +300,8 @@ do_ui(void) continue; } if ( process_key(key) != true ) { -printf("BLABL\n"); break; - } -printf("BLUBB\n"); + } else printf("XXXXX\n"); do_ui_update(false); } ui_thrd_force_update(); diff --git a/ui.h b/ui.h index d5a9123..7273a15 100644 --- a/ui.h +++ b/ui.h @@ -30,12 +30,7 @@ typedef int (*ui_callback)(WINDOW *, void *, bool); typedef int (*ui_input_callback)(WINDOW *, void *, int); -enum ui_type { - UI_ELEMENT, - UI_INPUT -}; - -union ui_data { +struct ui_data { ui_callback ui_element; ui_input_callback ui_input; }; diff --git a/ui_elements.c b/ui_elements.c index b9885a0..4b5c8cb 100644 --- a/ui_elements.c +++ b/ui_elements.c @@ -66,7 +66,8 @@ static int passwd_input_cb(WINDOW *wnd, void *data, int key) { struct input *a = (struct input *) data; - +printf("XXXXXXX\n"); +return DOUI_OK; /* * if ( process_key(key, pw_input, wnd_main) == false ) { * curs_set(0); -- cgit v1.2.3 From f2f6ea5029c6c43dc43d714978daca38c03a8a83 Mon Sep 17 00:00:00 2001 From: toni Date: Sun, 8 Nov 2015 20:28:30 +0100 Subject: - changed dir structure - fixed ipc semaphore/mq stuff --- Makefile | 4 +- config.h | 21 ----- main.c | 197 -------------------------------------- src/config.h | 21 +++++ src/main.c | 176 ++++++++++++++++++++++++++++++++++ src/opt.c | 46 +++++++++ src/opt.h | 35 +++++++ src/status.c | 29 ++++++ src/status.h | 7 ++ src/ui.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui.h | 66 +++++++++++++ src/ui_ani.c | 105 +++++++++++++++++++++ src/ui_ani.h | 43 +++++++++ src/ui_elements.c | 151 ++++++++++++++++++++++++++++++ src/ui_elements.h | 13 +++ src/ui_input.c | 201 +++++++++++++++++++++++++++++++++++++++ src/ui_input.h | 46 +++++++++ src/ui_ipc.c | 130 ++++++++++++++++++++++++++ src/ui_ipc.h | 52 +++++++++++ src/ui_nwindow.c | 157 +++++++++++++++++++++++++++++++ src/ui_nwindow.h | 44 +++++++++ src/ui_statusbar.c | 78 ++++++++++++++++ src/ui_statusbar.h | 32 +++++++ status.c | 29 ------ status.h | 7 -- tests/Makefile | 2 +- tests/semtest2.c | 2 +- ui.c | 268 ---------------------------------------------------- ui.h | 66 ------------- ui_ani.c | 76 --------------- ui_ani.h | 27 ------ ui_elements.c | 151 ------------------------------ ui_elements.h | 13 --- ui_input.c | 189 ------------------------------------- ui_input.h | 43 --------- ui_ipc.c | 139 --------------------------- ui_ipc.h | 52 ----------- ui_nwindow.c | 157 ------------------------------- ui_nwindow.h | 44 --------- ui_statusbar.c | 78 ---------------- ui_statusbar.h | 32 ------- 41 files changed, 1706 insertions(+), 1593 deletions(-) delete mode 100644 config.h delete mode 100644 main.c create mode 100644 src/config.h create mode 100644 src/main.c create mode 100644 src/opt.c create mode 100644 src/opt.h create mode 100644 src/status.c create mode 100644 src/status.h create mode 100644 src/ui.c create mode 100644 src/ui.h create mode 100644 src/ui_ani.c create mode 100644 src/ui_ani.h create mode 100644 src/ui_elements.c create mode 100644 src/ui_elements.h create mode 100644 src/ui_input.c create mode 100644 src/ui_input.h create mode 100644 src/ui_ipc.c create mode 100644 src/ui_ipc.h create mode 100644 src/ui_nwindow.c create mode 100644 src/ui_nwindow.h create mode 100644 src/ui_statusbar.c create mode 100644 src/ui_statusbar.h delete mode 100644 status.c delete mode 100644 status.h delete mode 100644 ui.c delete mode 100644 ui.h delete mode 100644 ui_ani.c delete mode 100644 ui_ani.h delete mode 100644 ui_elements.c delete mode 100644 ui_elements.h delete mode 100644 ui_input.c delete mode 100644 ui_input.h delete mode 100644 ui_ipc.c delete mode 100644 ui_ipc.h delete mode 100644 ui_nwindow.c delete mode 100644 ui_nwindow.h delete mode 100644 ui_statusbar.c delete mode 100644 ui_statusbar.h (limited to 'main.c') diff --git a/Makefile b/Makefile index 738afd3..9efaec9 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ INSTALL = install STRIP = strip VERSION = $(shell if [ -d ./.git ]; then echo -n "git-"; git rev-parse --short HEAD; else echo "1.2a"; fi) BIN = naskpass -SOURCES = status.c ui_ani.c ui_input.c ui_statusbar.c ui_nwindow.c ui.c ui_elements.c ui_ipc.c main.c +SOURCES = $(wildcard src/*.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) DEPS = $(patsubst %.c,%.d,$(SOURCES)) @@ -25,7 +25,7 @@ strip: $(OBJECTS) $(BIN) release: all strip debug: - $(MAKE) CFLAGS='$(CFLAGS) $(DBGFLAGS)' + @$(MAKE) CFLAGS='$(CFLAGS) $(DBGFLAGS)' @$(MAKE) -C tests CFLAGS='$(CFLAGS) $(DBGFLAGS)' install: diff --git a/config.h b/config.h deleted file mode 100644 index a7fddc0..0000000 --- a/config.h +++ /dev/null @@ -1,21 +0,0 @@ -#define AUTHOR "Toni Uhlig" -#define AUTHOR_EMAIL "matzeton@googlemail.com" -#define PKGNAME "naskpass" -#define PKGDESC "A NCurses replacement for cryptsetup's askpass." -#define DEFAULT_FIFO "/lib/cryptsetup/passfifo" -#define SHTDWN_CMD "echo 'o' >/proc/sysrq-trigger" - -#define SEM_GUI "/naskpass-gui" -#define SEM_INP "/naskpass-input" -#define SEM_BSY "/naskpass-busy" -#define SEM_RDY "/naskpass-initialized" -#define MSQ_PWD "/naskpass-passwd" -#define MSQ_INF "/naskpass-info" - -#define IPC_MQSIZ 128 - -#ifdef _VERSION -#define VERSION _VERSION -#else -#define VERSION "unknown" -#endif diff --git a/main.c b/main.c deleted file mode 100644 index 721be77..0000000 --- a/main.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "ui.h" -#include "ui_ipc.h" -#include "ui_ani.h" -#include "ui_input.h" -#include "ui_statusbar.h" - -#define MSG(msg_idx) msg_arr[msg_idx] - - -enum msg_index { - MSG_BUSY_FD = 0, - MSG_BUSY, - MSG_NO_FIFO, - MSG_FIFO_ERR, - MSG_NUM -}; -static const char *msg_arr[] = { "Please wait, got a piped password ..", "Please wait, busy ..", - "check_fifo: %s is not a FIFO\n", "check_fifo: %s error(%d): %s\n" }; - - -static void -usage(char *arg0) -{ - fprintf(stderr, "\n%s (%s)\n %s\n", PKGNAME, VERSION, PKGDESC); - fprintf(stderr, " Written by %s (%s).\n", AUTHOR, AUTHOR_EMAIL); - fprintf(stderr, " License GPLv3+: GNU GPL version 3 or later .\n\n"); - fprintf(stderr, " Command:\n\t%s [args]\n", arg0); - fprintf(stderr, " Arguments:\n\t-h this\n\t-f [passfifo] default: %s\n\t-c [cryptcreate]\n", DEFAULT_FIFO); -} - -static bool -check_fifo(char *fifo_path) -{ - struct stat st; - - if (mkfifo(fifo_path, S_IRUSR | S_IWUSR) == 0) { - return (true); - } else { - if (errno == EEXIST) { - if (stat(fifo_path, &st) == 0) { - if (S_ISFIFO(st.st_mode) == 1) { - return (true); - } else { - fprintf(stderr, MSG(MSG_NO_FIFO), fifo_path); - return (false); - } - } - } - } - fprintf(stderr, MSG(MSG_FIFO_ERR), fifo_path, errno, strerror(errno)); - return (false); -} - -int -run_cryptcreate(char *pass, char *crypt_cmd) -{ - int retval; - char *cmd; - - if (crypt_cmd == NULL || pass == NULL) return (-1); - asprintf(&cmd, "echo '%s' | %s", pass, crypt_cmd); - retval = system(cmd); - free(cmd); - return (retval); -} - -void sigfunc(int signal) -{ - switch (signal) { - case SIGTERM: - case SIGINT: - ui_ipc_semtrywait(SEM_UI); - ui_ipc_semtrywait(SEM_IN); - break; - } -} - -int -main(int argc, char **argv) -{ - int ret = EXIT_FAILURE, ffd = -1, c_status, opt; - pid_t child; - char pbuf[IPC_MQSIZ+1]; - char *fifo_path = NULL; - char *crypt_cmd = NULL; - struct timespec ts_sem_input; - - signal(SIGINT, sigfunc); - signal(SIGTERM, sigfunc); - - if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) { - fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno)); - goto error; - } - - if (ui_ipc_init(1) != 0) { - fprintf(stderr, "%s: can not create semaphore/message queue: %d (%s)\n", argv[0], errno, strerror(errno)); - goto error; - } - - memset(pbuf, '\0', IPC_MQSIZ+1); - while ((opt = getopt(argc, argv, "hf:c:")) != -1) { - switch (opt) { - case 'h': - usage(argv[0]); - goto error; - case 'f': - fifo_path = strdup(optarg); - break; - case 'c': - crypt_cmd = strdup(optarg); - break; - default: - usage(argv[0]); - goto error; - } - } - if (optind < argc) { - fprintf(stderr, "%s: I dont understand you.\n\n", argv[0]); - usage(argv[0]); - goto error; - } - if (fifo_path == NULL) fifo_path = strdup(DEFAULT_FIFO); - - if (check_fifo(fifo_path) == false) { - usage(argv[0]); - goto error; - } - if ((ffd = open(fifo_path, O_NONBLOCK | O_RDWR)) < 0) { - fprintf(stderr, "%s: fifo '%s' error: %d (%s)\n", argv[0], fifo_path, errno, strerror(errno)); - goto error; - } - - ui_ipc_sempost(SEM_UI); - if ((child = fork()) == 0) { - /* child */ - if (ffd >= 0) close(ffd); - if (crypt_cmd != NULL) free(crypt_cmd); - if (fifo_path != NULL) free(fifo_path); - fclose(stderr); - /* Slave process: TUI */ - do_ui(); - exit(0); - } else if (child > 0) { - /* parent */ - fclose(stdin); - fclose(stdout); - /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */ - while ( ui_ipc_getvalue(SEM_UI) > 0 || ui_ipc_getvalue(SEM_IN) > 0 ) { - if (read(ffd, pbuf, IPC_MQSIZ) >= 0) { - ui_ipc_sempost(SEM_BS); - ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY_FD), strlen(MSG(MSG_BUSY_FD))); - if (run_cryptcreate(pbuf, crypt_cmd) != 0) { - fprintf(stderr, "cryptcreate error\n"); - } - } else if ( ui_ipc_msgrecv(MQ_PW, pbuf, IPC_MQSIZ) > 0 ) { - ui_ipc_sempost(SEM_BS); - ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY), strlen(MSG(MSG_BUSY))); - if (run_cryptcreate(pbuf, crypt_cmd) != 0) { - fprintf(stderr, "cryptcreate error\n"); - } - ui_ipc_semwait(SEM_IN); - } - usleep(100000); - } - wait(&c_status); - memset(pbuf, '\0', IPC_MQSIZ+1); - } else { - /* fork error */ - perror("fork"); - goto error; - } - - ret = EXIT_SUCCESS; -error: - if (ffd >= 0) close(ffd); - if (crypt_cmd != NULL) free(crypt_cmd); - if (fifo_path != NULL) free(fifo_path); - ui_ipc_free(1); - exit(ret); -} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..a7fddc0 --- /dev/null +++ b/src/config.h @@ -0,0 +1,21 @@ +#define AUTHOR "Toni Uhlig" +#define AUTHOR_EMAIL "matzeton@googlemail.com" +#define PKGNAME "naskpass" +#define PKGDESC "A NCurses replacement for cryptsetup's askpass." +#define DEFAULT_FIFO "/lib/cryptsetup/passfifo" +#define SHTDWN_CMD "echo 'o' >/proc/sysrq-trigger" + +#define SEM_GUI "/naskpass-gui" +#define SEM_INP "/naskpass-input" +#define SEM_BSY "/naskpass-busy" +#define SEM_RDY "/naskpass-initialized" +#define MSQ_PWD "/naskpass-passwd" +#define MSQ_INF "/naskpass-info" + +#define IPC_MQSIZ 128 + +#ifdef _VERSION +#define VERSION _VERSION +#else +#define VERSION "unknown" +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5f0d6e9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "opt.h" + +#include "ui.h" +#include "ui_ipc.h" +#include "ui_ani.h" +#include "ui_input.h" +#include "ui_statusbar.h" + +#define MSG(msg_idx) msg_arr[msg_idx] + + +enum msg_index { + MSG_BUSY_FD = 0, + MSG_BUSY, + MSG_NO_FIFO, + MSG_FIFO_ERR, + MSG_FIFO_BUSY, + MSG_CRYPTCMD_ERR, + MSG_NUM +}; +static const char *msg_arr[] = { "Please wait, got a piped password ..", + "Please wait, busy ..", + "check_fifo: %s is not a FIFO\n", + "check_fifo: %s error(%d): %s\n", + "fifo: cryptcreate busy", + "cryptcreate error" + }; + + +static bool +check_fifo(char *fifo_path) +{ + struct stat st; + + if (mkfifo(fifo_path, S_IRUSR | S_IWUSR) == 0) { + return (true); + } else { + if (errno == EEXIST) { + if (stat(fifo_path, &st) == 0) { + if (S_ISFIFO(st.st_mode) == 1) { + return (true); + } else { + fprintf(stderr, MSG(MSG_NO_FIFO), fifo_path); + return (false); + } + } + } + } + fprintf(stderr, MSG(MSG_FIFO_ERR), fifo_path, errno, strerror(errno)); + return (false); +} + +int +run_cryptcreate(char *pass, char *crypt_cmd) +{ + int retval; + char *cmd; + + if (crypt_cmd == NULL || pass == NULL) return (-1); + asprintf(&cmd, "echo '%s' | %s", pass, crypt_cmd); + retval = system(cmd); + free(cmd); + return (retval); +} + +void sigfunc(int signal) +{ + switch (signal) { + case SIGTERM: + case SIGINT: + ui_ipc_semtrywait(SEM_UI); + ui_ipc_semtrywait(SEM_IN); + break; + } +} + +int +main(int argc, char **argv) +{ + int ret = EXIT_FAILURE, ffd = -1, c_status; + pid_t child; + char pbuf[IPC_MQSIZ+1]; + struct timespec ts_sem_input; + + signal(SIGINT, sigfunc); + signal(SIGTERM, sigfunc); + + if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) { + fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + + if (ui_ipc_init(1) != 0) { + fprintf(stderr, "%s: can not create semaphore/message queue: %d (%s)\n", argv[0], errno, strerror(errno)); + goto error; + } + + memset(pbuf, '\0', IPC_MQSIZ+1); + parse_cmd(argc, argv); + if (check_fifo(GETOPT(FIFO_PATH).str) == false) { + usage(argv[0]); + goto error; + } + if ((ffd = open(GETOPT(FIFO_PATH).str, O_NONBLOCK | O_RDWR)) < 0) { + fprintf(stderr, "%s: fifo '%s' error: %d (%s)\n", argv[0], GETOPT(FIFO_PATH).str, errno, strerror(errno)); + goto error; + } + + ui_ipc_sempost(SEM_UI); + if ((child = fork()) == 0) { + /* child */ + if (ffd >= 0) close(ffd); + fclose(stderr); + /* Slave process: TUI */ + if (ui_ipc_init(0) == 0) { + ui_ipc_semwait(SEM_BS); + do_ui(); + } + exit(0); + } else if (child > 0) { + /* parent */ + fclose(stdin); + fclose(stdout); + ui_ipc_sempost(SEM_BS); + ui_ipc_sempost(SEM_UI); + /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */ + while ( ui_ipc_getvalue(SEM_UI) > 0 || ui_ipc_getvalue(SEM_IN) > 0 ) { + ui_ipc_sempost(SEM_BS); + if (read(ffd, pbuf, IPC_MQSIZ) >= 0) { + ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY_FD), strlen(MSG(MSG_BUSY_FD))); + if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) { + ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR), strlen(MSG(MSG_CRYPTCMD_ERR))); + } + } else if ( ui_ipc_msgrecv(MQ_PW, pbuf, IPC_MQSIZ) != (int)-1 ) { + ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY), strlen(MSG(MSG_BUSY))); + if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) { + ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR), strlen(MSG(MSG_CRYPTCMD_ERR))); + } + ui_ipc_semwait(SEM_IN); + } + ui_ipc_semwait(SEM_BS); + usleep(100000); + waitpid(child, &c_status, WNOHANG); + if ( WIFSIGNALED(c_status) != 0 ) { + break; + } + } + wait(&c_status); + memset(pbuf, '\0', IPC_MQSIZ+1); + } else { + /* fork error */ + perror("fork"); + goto error; + } + + ret = EXIT_SUCCESS; +error: + if (ffd >= 0) close(ffd); + ui_ipc_free(1); + exit(ret); +} diff --git a/src/opt.c b/src/opt.c new file mode 100644 index 0000000..7b6d083 --- /dev/null +++ b/src/opt.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +#include "config.h" +#include "opt.h" + +#define CONFIG_OPT(default_val) { {0},0,{default_val} } + +struct opt config_opts[] = { CONFIG_OPT(DEFAULT_FIFO), CONFIG_OPT(NULL) }; +const int opt_siz = ( sizeof(config_opts)/sizeof(config_opts[0]) ); + + +void +usage(char *arg0) +{ + fprintf(stderr, "\n%s (%s)\n %s\n", PKGNAME, VERSION, PKGDESC); + fprintf(stderr, " Written by %s (%s).\n", AUTHOR, AUTHOR_EMAIL); + fprintf(stderr, " License GPLv3+: GNU GPL version 3 or later .\n\n"); + fprintf(stderr, " Command:\n\t%s [args]\n", arg0); + fprintf(stderr, " Arguments:\n\t-h this\n\t-f [passfifo] default: %s\n\t-c [cryptcreate]\n", DEFAULT_FIFO); +} + +int +parse_cmd(int argc, char **argv) +{ + int opt; + + while ((opt = getopt(argc, argv, "hf:c:")) != -1) { + switch (opt) { + case 'h': + usage(argv[0]); + return 1; + case 'f': + s_OPT(FIFO_PATH, strdup(optarg)); + break; + case 'c': + s_OPT(CRYPT_CMD, strdup(optarg)); + break; + } + } + return 0; +} + diff --git a/src/opt.h b/src/opt.h new file mode 100644 index 0000000..6d66101 --- /dev/null +++ b/src/opt.h @@ -0,0 +1,35 @@ +#ifndef OPT_H +#define OPT_H 1 + +#define OPT(opt_index) config_opts[opt_index] +#define GETOPT(opt_index) OPT(opt_index).opt +#define OPT_USED(opt_index, uvalue) OPT(opt_index).found = uvalue; +#define d_OPT(opt_index, rvalue) OPT(opt_index).opt.dec = rvalue; OPT_USED(opt_index, 1); +#define s_OPT(opt_index, rvalue) OPT(opt_index).opt.str = rvalue; OPT_USED(opt_index, 1); + +union opt_entry { + char *str; + int *dec; +}; + +struct opt { + union opt_entry opt; + unsigned char found; + const union opt_entry def; +}; + +enum opt_index { + FIFO_PATH = 0, + CRYPT_CMD +}; + + +extern struct opt config_opts[]; + +void +usage(char *arg0); + +int +parse_cmd(int argc, char **argv); + +#endif diff --git a/src/status.c b/src/status.c new file mode 100644 index 0000000..5286ddf --- /dev/null +++ b/src/status.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +#include "status.h" + + +char * +get_system_stat(void) +{ + char *retstr = NULL; + int ncpu; + struct sysinfo inf; + + if (sysinfo(&inf) == EFAULT) { + return ("[SYSINFO ERROR]"); + } + ncpu = get_nprocs(); + + if (asprintf(&retstr, "u:%04ld - l:%3.2f,%3.2f,%3.2f - %dcore%s - mem:%lu/%lumb - procs:%02d", + inf.uptime, ((float)inf.loads[0]/10000), ((float)inf.loads[1]/10000), ((float)inf.loads[2]/10000), + ncpu, (ncpu > 1 ? "s" : ""), + (unsigned long)((inf.freeram/1024)/1024), (unsigned long)((inf.totalram/1024)/1024), inf.procs) == -1) { + return ("[ASPRINTF ERROR]"); + } + return (retstr); +} diff --git a/src/status.h b/src/status.h new file mode 100644 index 0000000..995d08a --- /dev/null +++ b/src/status.h @@ -0,0 +1,7 @@ +#ifndef STATUS_H +#define STATUS_H 1 + +char * +get_system_stat(void); + +#endif diff --git a/src/ui.c b/src/ui.c new file mode 100644 index 0000000..2fb5a1f --- /dev/null +++ b/src/ui.c @@ -0,0 +1,270 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui.h" +#include "ui_ipc.h" +#include "ui_elements.h" +#include "ui_ani.h" +#include "ui_input.h" +#include "ui_statusbar.h" +#include "ui_nwindow.h" + +#include "status.h" +#include "config.h" + +#define APP_TIMEOUT 60 +#define APP_TIMEOUT_FMT "%02d" +#define PASSWD_WIDTH 35 +#define PASSWD_HEIGHT 5 +#define PASSWD_XRELPOS (unsigned int)(PASSWD_WIDTH / 2) - (PASSWD_WIDTH / 6) +#define PASSWD_YRELPOS (unsigned int)(PASSWD_HEIGHT / 2) + 1 +#define INFOWND_WIDTH 25 +#define INFOWND_HEIGHT 3 +#define INFOWND_XRELPOS (unsigned int)(INFOWND_WIDTH / 2) - (INFOWND_WIDTH / 6) +#define INFOWND_YRELPOS (unsigned int)(INFOWND_HEIGHT / 2) + 1 + +#define STRLEN(s) (sizeof(s)/sizeof(s[0])) + + +static unsigned int max_x, max_y; +static WINDOW *wnd_main; +static struct nask_ui /* simple linked list to all UI objects */ *nui = NULL, + /* current active input */ *active = NULL; +static pthread_t thrd; +static unsigned int atmout = APP_TIMEOUT; +static pthread_cond_t cnd_update = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t mtx_update = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mtx_busy = PTHREAD_MUTEX_INITIALIZER; + + +void +register_ui_elt(struct ui_callbacks *cbs, void *data, WINDOW *wnd) +{ + struct nask_ui *tmp, *new; + + new = calloc(1, sizeof(struct nask_ui)); + new->cbs = *cbs; + new->wnd = wnd; + new->data = data; + new->next = NULL; + if (nui == NULL) { + nui = new; + nui->next = NULL; + } else { + tmp = nui; + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = new; + } +} + +void +unregister_ui_elt(void *data) +{ + struct nask_ui *cur, *next, *before = NULL; + + cur = nui; + while (cur != NULL) { + next = cur->next; + if (cur->data != NULL && cur->data == data) { + free(cur); + if (before != NULL) { + before->next = next; + } else { + nui = next; + } + } + before = cur; + cur = next; + } +} + +int +activate_ui_input(void *data) +{ + struct nask_ui *cur = nui; + + if (cur == NULL || data == NULL) return DOUI_NINIT; + while ( cur->data != NULL ) { + if ( cur->data == data ) { + if ( cur->cbs.ui_input != NULL && cur->cbs.ui_input(cur->wnd, data, UIKEY_ACTIVATE) == DOUI_OK ) { + active = cur; + return DOUI_OK; + } + } + cur = cur->next; + } + return DOUI_ERR; +} + +int +reactivate_ui_input(void) +{ + if (active) { + if (active->cbs.ui_element) { + } + return ( active->cbs.ui_input(active->wnd, active->data, UIKEY_ACTIVATE) ); + } else return DOUI_ERR; +} + +static bool +process_key(char key) +{ + atmout = APP_TIMEOUT; + if ( active != NULL ) { + return ( active->cbs.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false ); + } + return false; +} + +static int +do_ui_update(bool timed_out) +{ + int retval = UICB_OK; + int curx = getcurx(wnd_main); + int cury = getcury(wnd_main); + struct nask_ui *cur = nui; + + /* call all draw callback's */ + erase(); + while (cur != NULL) { + if (cur->cbs.ui_element != NULL) { + cur->cbs.ui_element(cur->wnd, cur->data, timed_out); + doupdate(); + } else { + retval = UICB_ERR_CB; + } + cur = cur->next; + } + /* TODO: Maybe export to an extra module? */ + attron(COLOR_PAIR(1)); + mvprintw(0, max_x - STRLEN(APP_TIMEOUT_FMT), "[" APP_TIMEOUT_FMT "]", atmout); + attroff(COLOR_PAIR(1)); + /* EoT (End of Todo) */ + wmove(wnd_main, cury, curx); + wrefresh(wnd_main); + return (retval); +} + +static void * +ui_thrd(void *arg) +{ + int cnd_ret; + struct timeval now; + struct timespec wait; + + gettimeofday(&now, NULL); + wait.tv_sec = now.tv_sec + UILOOP_TIMEOUT; + wait.tv_nsec = now.tv_usec * 1000; + do_ui_update(true); + ui_ipc_sempost(SEM_RD); + pthread_mutex_lock(&mtx_update); + while ( ui_ipc_getvalue(SEM_UI) > 0 ) { + pthread_mutex_unlock(&mtx_busy); + cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &wait); + pthread_mutex_lock(&mtx_busy); + if (--atmout == 0) ui_ipc_semtrywait(SEM_UI); + do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) ); + if (cnd_ret == ETIMEDOUT) { + wait.tv_sec += UILOOP_TIMEOUT; + } + } + pthread_mutex_unlock(&mtx_update); + return (NULL); +} + +void +ui_thrd_force_update(void) +{ + pthread_mutex_lock(&mtx_busy); + pthread_cond_signal(&cnd_update); + pthread_mutex_unlock(&mtx_busy); +} + +WINDOW * +init_ui(void) +{ + wnd_main = initscr(); + max_x = getmaxx(wnd_main); + max_y = getmaxy(wnd_main); + start_color(); + init_pair(1, COLOR_RED, COLOR_WHITE); + init_pair(2, COLOR_WHITE, COLOR_BLACK); + init_pair(3, COLOR_BLACK, COLOR_WHITE); + init_pair(4, COLOR_YELLOW, COLOR_RED); + raw(); + keypad(stdscr, TRUE); + noecho(); + cbreak(); + return (wnd_main); +} + +void +free_ui(void) +{ + delwin(wnd_main); + endwin(); + clear(); + printf(" \033[2J\n"); +} + +static int +run_ui_thrd(void) { + return (pthread_create(&thrd, NULL, &ui_thrd, NULL)); +} + +static int +stop_ui_thrd(void) +{ + return (pthread_join(thrd, NULL)); +} + +int +do_ui(void) +{ + char key = '\0'; + int ret = DOUI_ERR; + + /* init TUI and UI Elements (input field, status bar, etc) */ + init_ui(); + init_ui_elements(wnd_main, max_x, max_y); + + pthread_mutex_lock(&mtx_update); + if (run_ui_thrd() != 0) { + return ret; + } + ui_ipc_semwait(SEM_RD); + wtimeout(wnd_main, 1000); + pthread_mutex_unlock(&mtx_update); + while ( ui_ipc_getvalue(SEM_UI) > 0 ) { + if ((key = wgetch(wnd_main)) == '\0') { + break; + } + if (key == -1) { + continue; + } + if ( process_key(key) != true ) { + ui_ipc_semtrywait(SEM_UI); + ui_thrd_force_update(); + } + } + stop_ui_thrd(); + free_ui_elements(); + + return DOUI_OK; +} + diff --git a/src/ui.h b/src/ui.h new file mode 100644 index 0000000..91d5403 --- /dev/null +++ b/src/ui.h @@ -0,0 +1,66 @@ +#ifndef UI_H +#define UI_H 1 + +#include +#include + +#define UICB_OK 0 +#define UICB_ERR_UNDEF 1 +#define UICB_ERR_CB 2 +#define UICB_ERR_BUF 3 + +#define DOUI_OK 0 +#define DOUI_ERR 1 +#define DOUI_TMOUT 2 +#define DOUI_NINIT 3 + +#define UILOOP_TIMEOUT 1 + +#define UIKEY_ACTIVATE 0 +#define UIKEY_ENTER 10 +#define UIKEY_BACKSPACE 7 +#define UIKEY_ESC 27 +#define UIKEY_DOWN 2 +#define UIKEY_UP 3 +#define UIKEY_LEFT 4 +#define UIKEY_RIGHT 5 + + +typedef int (*uicb_base)(WINDOW *, void *, bool); +typedef int (*uicb_input)(WINDOW *, void *, int); + + +struct ui_callbacks { + uicb_base ui_element; + uicb_input ui_input; +}; + +struct nask_ui { + struct ui_callbacks cbs; + WINDOW *wnd; + void *data; + struct nask_ui *next; +}; + +void +register_ui_elt(struct ui_callbacks *cbs, void *data, WINDOW *wnd); + +void +unregister_ui_elt(void *data); + +int +activate_ui_input(void *data); + +void +ui_thrd_force_update(void); + +WINDOW * +init_ui(void); + +void +free_ui(void); + +int +do_ui(void); + +#endif diff --git a/src/ui_ani.c b/src/ui_ani.c new file mode 100644 index 0000000..d1f1073 --- /dev/null +++ b/src/ui_ani.c @@ -0,0 +1,105 @@ +#include +#include + +#include "ui.h" +#include "ui_ani.h" + +#define ANIC_INITSTATE '|' + + +struct anic * +init_anic_default(unsigned int x, unsigned int y, chtype attrs, char *fmt) +{ + struct anic *a = init_anic(x, y, attrs, anic_cb); + struct anic_default *b = calloc(1, sizeof(struct anic_default)); + + a->data = (void *) b; + b->state = ANIC_INITSTATE; + if (fmt != NULL) { + b->fmt = strdup(fmt); + } + return (a); +} + +struct anic * +init_anic(unsigned int x, unsigned int y, chtype attrs, uicb_anic uicb) +{ + struct anic *a = calloc(1, sizeof(struct anic)); + + a->x = x; + a->y = y; + a->uicb = uicb; + a->attrs = attrs; + return (a); +} + +void +free_anic(struct anic *a) +{ + free(a); +} + +void +free_anic_default(struct anic *a) +{ + struct anic_default *b; + + if (a->data != NULL) { + b = (struct anic_default *) a->data; + free(b->fmt); + free(b); + } + free_anic(a); +} + +int +anic_cb(WINDOW *win, void *data, bool timed_out) +{ + struct anic *a = (struct anic *) data; + struct anic_default *b; + char *tmp; + int retval = UICB_OK; + + if (a == NULL) return (UICB_ERR_UNDEF); + b = (struct anic_default *) a->data; + if (timed_out == true) { + switch (b->state) { + default: + case '|': b->state = '/'; break; + case '/': b->state = '-'; break; + case '-': b->state = '\\'; break; + case '\\': b->state = '|'; break; + } + } + attron(a->attrs); + if (b->fmt != NULL) { + if (asprintf(&tmp, b->fmt, b->state) <= 0) { + retval = UICB_ERR_BUF; + } + } else { + asprintf(&tmp, "%c", b->state); + } + if (win != NULL) { + mvwprintw(win, a->y, a->x, tmp); + } else { + mvprintw(a->y, a->x, tmp); + } + free(tmp); + attroff(a->attrs); + return (retval); +} + +void +register_anic(struct anic *a, uicb_anic uicb) +{ + struct ui_callbacks cbs; + cbs.ui_element = uicb; + cbs.ui_input = NULL; + register_ui_elt(&cbs, (void *) a, NULL); +} + +void +register_anic_default(struct anic *a) +{ + register_anic(a, anic_cb); +} diff --git a/src/ui_ani.h b/src/ui_ani.h new file mode 100644 index 0000000..3d6ece2 --- /dev/null +++ b/src/ui_ani.h @@ -0,0 +1,43 @@ +#ifndef UI_ANIC_H +#define UI_ANIC_H 1 + +#include + + +typedef int (*uicb_anic)(WINDOW *, void *, bool); + +struct anic_default { + char state; + char *fmt; +}; + +struct anic { + unsigned int x; + unsigned int y; + uicb_anic uicb; + void *data; + chtype attrs; +}; + +struct anic * +init_anic_default(unsigned int x, unsigned int y, chtype attrs, char *fmt); + +struct anic * +init_anic(unsigned int x, unsigned int y, chtype attrs, uicb_anic uicb); + +void +free_anic_default(struct anic *a); + +void +free_anic(struct anic *a); + +int +anic_cb(WINDOW *win, void *data, bool timed_out); + +void +register_anic(struct anic *a, uicb_anic uicb); + +void +register_anic_default(struct anic *a); + +#endif diff --git a/src/ui_elements.c b/src/ui_elements.c new file mode 100644 index 0000000..29c2e32 --- /dev/null +++ b/src/ui_elements.c @@ -0,0 +1,151 @@ +#include +#include +#include + +#include "ui.h" +#include "ui_ipc.h" +#include "ui_ani.h" +#include "ui_input.h" +#include "ui_statusbar.h" +#include "ui_nwindow.h" +#include "ui_elements.h" + +#include "status.h" + +#define PASSWD_WIDTH 35 +#define PASSWD_HEIGHT 5 +#define PASSWD_XRELPOS (unsigned int)(PASSWD_WIDTH / 2) - (PASSWD_WIDTH / 6) +#define PASSWD_YRELPOS (unsigned int)(PASSWD_HEIGHT / 2) + 1 +#define INFOWND_WIDTH 25 +#define INFOWND_HEIGHT 3 +#define INFOWND_XRELPOS (unsigned int)(INFOWND_WIDTH / 2) - (INFOWND_WIDTH / 6) +#define INFOWND_YRELPOS (unsigned int)(INFOWND_HEIGHT / 2) + 1 + +static struct input *pw_input; +static struct anic *heartbeat; +static struct statusbar *higher, *lower; +static struct txtwindow *infownd; +static char *title = NULL; + + +static int +lower_statusbar_update(WINDOW *win, struct statusbar *bar) +{ + char *tmp = get_system_stat(); + set_statusbar_text(bar, tmp); + free(tmp); + return 0; +} + +static int +higher_statusbar_update(WINDOW *win, struct statusbar *bar) +{ + return 0; +} + +static int +infownd_update(WINDOW *win, struct txtwindow *tw) +{ + char *tmp = (char*)(tw->userptr); + size_t len = strlen(tmp); + + if (tw->active) { + if ( len == 3 ) { + memset(tmp+1, '\0', 2); + } else strcat(tmp, "."); + } else (*tmp) = '.'; + return 0; +} + +static int +mq_passwd_send(char *passwd, size_t len) +{ + int ret; + + ui_ipc_sempost(SEM_IN); + ret = ui_ipc_msgsend(MQ_PW, passwd, len); + return ret; +} + +static int +passwd_input_cb(WINDOW *wnd, void *data, int key) +{ + struct input *a = (struct input *) data; +/* + * if ( process_key(key, pw_input, wnd_main) == false ) { + * curs_set(0); + * memset(mq_msg, '\0', IPC_MQSIZ+1); + * mq_receive(mq_info, mq_msg, IPC_MQSIZ+1, 0); + * set_txtwindow_text(infownd, mq_msg); + * set_txtwindow_active(infownd, true); + * sleep(3); + * sem_trywait(sp_ui); + * } + * activate_input(wnd_main, pw_input); + */ + switch (key) { + case UIKEY_ENTER: + mq_passwd_send(a->input, a->input_len); + clear_input(wnd, a); + set_txtwindow_text(infownd, "BLA"); + set_txtwindow_active(infownd, true); + break; + case UIKEY_BACKSPACE: + del_input(wnd, a); + break; + case UIKEY_ESC: + return DOUI_ERR; + case UIKEY_DOWN: + case UIKEY_UP: + case UIKEY_LEFT: + case UIKEY_RIGHT: + break; + case UIKEY_ACTIVATE: + break; + default: + add_input(wnd, a, key); + } + return DOUI_OK; +} + +void +init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y) +{ + asprintf(&title, "/* %s-%s */", PKGNAME, VERSION); + pw_input = init_input((unsigned int)(max_x / 2)-PASSWD_XRELPOS, (unsigned int)(max_y / 2)-PASSWD_YRELPOS, PASSWD_WIDTH, "PASSWORD: ", IPC_MQSIZ, COLOR_PAIR(3), COLOR_PAIR(2)); + heartbeat = init_anic_default(0, 0, A_BOLD | COLOR_PAIR(1), "[%c]"); + higher = init_statusbar(0, max_x, A_BOLD | COLOR_PAIR(3), higher_statusbar_update); + lower = init_statusbar(max_y - 1, max_x, COLOR_PAIR(3), lower_statusbar_update); + infownd = init_txtwindow((unsigned int)(max_x / 2)-INFOWND_XRELPOS, (unsigned int)(max_y / 2)-INFOWND_YRELPOS, INFOWND_WIDTH, INFOWND_HEIGHT, COLOR_PAIR(4), COLOR_PAIR(4) | A_BOLD, infownd_update); + infownd->userptr = calloc(4, sizeof(char)); + (*(char*)(infownd->userptr)) = '.'; + + register_input(NULL, pw_input, passwd_input_cb); + register_statusbar(higher); + register_statusbar(lower); + register_anic_default(heartbeat); + register_txtwindow(infownd); + set_txtwindow_title(infownd, "WARNING"); + activate_input(wnd_main, pw_input); + set_statusbar_text(higher, title); +} + +void +free_ui_elements(void) +{ + unregister_ui_elt(lower); + unregister_ui_elt(higher); + unregister_ui_elt(heartbeat); + unregister_ui_elt(pw_input); + free_input(pw_input); + free_anic_default(heartbeat); + free_statusbar(higher); + free_statusbar(lower); + free(infownd->userptr); + free_txtwindow(infownd); + free_ui(); + if (title) { + free(title); + title = NULL; + } +} diff --git a/src/ui_elements.h b/src/ui_elements.h new file mode 100644 index 0000000..0cf8826 --- /dev/null +++ b/src/ui_elements.h @@ -0,0 +1,13 @@ +#ifndef UI_ELEMENTS_H +#define UI_ELEMENTS_H 1 + +#include "config.h" + + +void +init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y); + +void +free_ui_elements(void); + +#endif diff --git a/src/ui_input.c b/src/ui_input.c new file mode 100644 index 0000000..5f9a679 --- /dev/null +++ b/src/ui_input.c @@ -0,0 +1,201 @@ +#include +#include + +#include "ui.h" +#include "ui_input.h" + + +struct input * +init_input(unsigned int x, unsigned int y, unsigned int width, char *prompt, size_t input_len, chtype attrs, chtype shadow) +{ + struct input *a = calloc(1, sizeof(struct input)); + + a->x = x; + a->y = y; + a->width = width; + a->cur_pos = 0; + a->input = calloc(input_len+1, sizeof(char)); + a->input_max = input_len; + a->input_len = 0; + a->input_pos = 0; + a->prompt = strdup(prompt); + a->attrs = attrs; + a->shadow = shadow; + return (a); +} + +void +free_input(struct input *a) +{ + if (a->input != NULL) { + free(a->input); + } + free(a->prompt); + free(a); +} + +static void +print_wnd(size_t addwidth, struct input *a) +{ + int i, x = a->x, y = a->y; + size_t relwidth = addwidth*2, len = strlen(a->prompt) + a->width; + char tmp[len+relwidth+1]; + + attron(a->attrs); + memset(tmp, ' ', len+relwidth); + tmp[len+relwidth] = '\0'; + for (i = -1; i <= 1; i++) + mvprintw(y+i, x-addwidth, tmp); + + mvhline(y-2, x-addwidth, 0, len+relwidth); + mvhline(y+2, x-addwidth, 0, len+relwidth); + mvvline(y-1, x-addwidth-1, 0, 3); + mvvline(y-1, x+len+addwidth, 0, 3); + mvaddch(y-2, x-addwidth-1, ACS_ULCORNER); + mvaddch(y+2, x-addwidth-1, ACS_LLCORNER); + mvaddch(y-2, x+len+addwidth, ACS_URCORNER); + mvaddch(y+2, x+len+addwidth, ACS_LRCORNER); + attroff(a->attrs); + + attron(a->shadow); + for (i = x-addwidth+1; i < x+len+relwidth; i++) + mvaddch(y+3, i, ACS_CKBOARD); + for (i = -1; i < 3; i++) { + mvaddch(y+i, x+len+relwidth-2, ACS_CKBOARD); + mvaddch(y+i, x+len+relwidth-1, ACS_CKBOARD); + } + attroff(a->shadow); +} + +static void +print_input_text(WINDOW *win, struct input *a) +{ + size_t start = 0; + size_t p_len = strlen(a->prompt); + + char tmp[a->width + 1]; + memset(tmp, '\0', a->width + 1); + if (a->input_pos >= a->width) { + start = a->input_pos - a->width; + } + + strncpy(tmp, (char *)(a->input + start), a->width); + int i; + for (i = 0; i < strlen(tmp); i++) { + tmp[i] = '*'; + } + + if (win == NULL) { + mvprintw(a->y, a->x + p_len, "%s", tmp); + } else { + mvwprintw(win, a->y, a->x + p_len, "%s", tmp); + } +} + +static void +print_input(WINDOW *win, struct input *a) +{ + char *tmp; + int i; + size_t p_len = strlen(a->prompt); + + print_wnd(3, a); + attron(a->attrs); + if (win) { + mvwprintw(win, a->y, a->x, a->prompt); + } else { + mvprintw(a->y, a->x, a->prompt); + } + tmp = calloc(a->width+1, sizeof(char)); + for (i = 0; i < a->width; i++) { + *(tmp + i) = '_'; + } + if (win) { + mvwprintw(win, a->y, a->x + p_len, tmp); + } else { + mvprintw(a->y, a->x + p_len, tmp); + } + free(tmp); + print_input_text(win, a); + attroff(a->attrs); +} + +int +activate_input(WINDOW *win, struct input *a) +{ + if (a == NULL) return (UICB_ERR_UNDEF); + size_t p_len = strlen(a->prompt); + if (win == NULL) { + move(a->y, a->x + p_len + a->cur_pos); + } else { + wmove(win, a->y, a->x + p_len + a->cur_pos); + } + return (activate_ui_input( (void *) a )); +} + +int +add_input(WINDOW *win, struct input *a, int key) +{ + if (a == NULL) return (UICB_ERR_UNDEF); + if (a->input_len >= a->input_max) return (UICB_ERR_BUF); + *(a->input + a->input_pos) = (char) key; + ++a->input_pos; + ++a->input_len; + a->cur_pos = (a->cur_pos+1 < a->width ? a->cur_pos+1 : a->cur_pos); + print_input(win, a); + return (UICB_OK); +} + +int +del_input(WINDOW *win, struct input *a) +{ + if (a == NULL) return (UICB_ERR_UNDEF); + if (a->input_len == 0) return (UICB_ERR_BUF); + memmove((a->input + a->input_pos - 1), (a->input + a->input_pos), a->input_max - a->input_pos); + --a->input_len; + *(a->input + a->input_len) = '\0'; + if (a->input_pos-1 == a->input_len) { + --a->input_pos; + } + if (a->cur_pos+1 < a->width && a->cur_pos > 0) { + --a->cur_pos; + } else if (a->cur_pos-1 == a->input_pos) { + --a->cur_pos; + } + mvwprintw(win, a->y, a->x + a->cur_pos + strlen(a->prompt), "_"); + print_input(win, a); + return (UICB_OK); +} + +int +clear_input(WINDOW *win, struct input *a) +{ + if (a == NULL) return (UICB_ERR_UNDEF); + memset(a->input, '\0', a->input_max); + a->input_len = 0; + a->input_pos = 0; + a->cur_pos = 0; + print_input(win, a); + return (UICB_OK); +} + +static int +input_cb(WINDOW *win, void *data, bool timed_out) +{ + struct input *a = (struct input *) data; + + if (a == NULL) return (UICB_ERR_UNDEF); + if (win != NULL && is_wintouched(win) == false) return (UICB_OK); + print_input(win, a); + return (UICB_OK); +} + +void +register_input(WINDOW *win, struct input *a, uicb_input ipcb) +{ + struct ui_callbacks cbs; + cbs.ui_element = input_cb; + cbs.ui_input = ipcb; + register_ui_elt(&cbs, (void *) a, win); +} + diff --git a/src/ui_input.h b/src/ui_input.h new file mode 100644 index 0000000..657c926 --- /dev/null +++ b/src/ui_input.h @@ -0,0 +1,46 @@ +#ifndef UI_INPUT_H +#define UI_INPUT_H 1 + +#include + + +struct input { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int cur_pos; + char *input; + size_t input_max; + size_t input_len; + size_t input_pos; + char *prompt; + chtype attrs; + chtype shadow; + uicb_input cb_input; +}; + +struct input * +init_input(unsigned int x, unsigned int y, unsigned int width, char *prompt, size_t input_len, chtype attrs, chtype shadow); + +void +free_input(struct input *a); + +int +activate_input(WINDOW *win, struct input *a); + +int +add_input(WINDOW *win, struct input *a, int key); + +int +del_input(WINDOW *win, struct input *a); + +int +clear_input(WINDOW *win, struct input *a); + +void +register_input(WINDOW *win, struct input *a, uicb_input ipcb); + +void +unregister_input(struct input *a); + +#endif diff --git a/src/ui_ipc.c b/src/ui_ipc.c new file mode 100644 index 0000000..9eac79e --- /dev/null +++ b/src/ui_ipc.c @@ -0,0 +1,130 @@ +#include +#include +#include +#ifdef SEM_TIMEDWAIT +#include +#endif +#include +#include +#include +#include + +#include "ui_ipc.h" + +#define JMP_IF(cmd, retval, jmplabel) if ( (cmd) == retval ) { printf("(%s) == %p\n", #cmd, (void*)retval); goto jmplabel; } + + +static sem_t *sems[SEM_NUM]; +static mqd_t msqs[MSQ_NUM]; + + +int +ui_ipc_init(int is_master) +{ + volatile int sp_oflags, mq_oflags; + mode_t crt_flags; + struct mq_attr m_attr; + + bzero(sems, sizeof(sem_t*)*SEM_NUM); + bzero(msqs, sizeof(mqd_t)*MSQ_NUM); + m_attr.mq_flags = 0; + m_attr.mq_msgsize = IPC_MQSIZ; + m_attr.mq_maxmsg = 3; + m_attr.mq_curmsgs = 0; + if (is_master) { + sp_oflags = O_CREAT | O_EXCL; + mq_oflags = O_NONBLOCK | O_CREAT | O_EXCL; + crt_flags = S_IRUSR | S_IWUSR; + JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + } else { + sp_oflags = 0; + mq_oflags = 0; + crt_flags = 0; + JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); + } + JMP_IF( sems[SEM_UI] = sem_open(SEM_GUI, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_IN] = sem_open(SEM_INP, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_BS] = sem_open(SEM_BSY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + JMP_IF( sems[SEM_RD] = sem_open(SEM_RDY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); + return 0; +error: + return errno; +} + +void +ui_ipc_free(int is_master) +{ + int i; + + for (i = 0; i < SEM_NUM; i++) { + if (sems[i]) sem_close(sems[i]); + } + for (i = 0; i < MSQ_NUM; i++) { + if (msqs[i]) mq_close(msqs[i]); + } + if (is_master > 0) { + sem_unlink(SEM_BSY); + sem_unlink(SEM_GUI); + sem_unlink(SEM_INP); + sem_unlink(SEM_RDY); + mq_unlink(MSQ_PWD); + mq_unlink(MSQ_INF); + } +} + +int +ui_ipc_sempost(enum UI_IPC_SEM e_sp) +{ + return ( sem_post(sems[e_sp]) ); +} + +int +ui_ipc_semwait(enum UI_IPC_SEM e_sp) +{ + return ( sem_wait(sems[e_sp]) ); +} + +int +ui_ipc_semtrywait(enum UI_IPC_SEM e_sp) +{ + return ( sem_trywait(sems[e_sp]) ); +} + +int +ui_ipc_getvalue(enum UI_IPC_SEM e_sp) +{ + int sp_val = 0; + + if (sem_getvalue(sems[e_sp], &sp_val) != 0) { + return -1; + } + return sp_val; +} + +#ifdef SEM_TIMEDWAIT +int +ui_ipc_semtimedwait(enum UI_IPC_SEM e_sp, int timeout) +{ + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + return -1; + } + ts.tc_sec += timeout; + return ( sem_timedwait(sems[q_mq], &ts) ); +} +#endif + +int +ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len) +{ + return ( mq_send(msqs[e_mq], msg_ptr, msg_len, 0) ); +} + +ssize_t +ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len) +{ + return ( mq_receive(msqs[e_mq], msg_ptr, msg_len, NULL) ); +} + diff --git a/src/ui_ipc.h b/src/ui_ipc.h new file mode 100644 index 0000000..2c5bcb5 --- /dev/null +++ b/src/ui_ipc.h @@ -0,0 +1,52 @@ +#ifndef UI_IPC_H +#define UI_IPC_H 1 + +#include "status.h" +#include "config.h" + + +enum UI_IPC_SEM { + SEM_RD = 0, /* UI Init done? */ + SEM_UI, /* TUI active? */ + SEM_IN, /* Textfield has input avail */ + SEM_BS, /* Master process busy */ + SEM_NUM +}; + +enum UI_IPC_MSQ { + MQ_PW = 0, + MQ_IF, + MSQ_NUM +}; + + +int +ui_ipc_init(int is_master); + +void +ui_ipc_free(int is_master); + +int +ui_ipc_sempost(enum UI_IPC_SEM e_sp); + +int +ui_ipc_semwait(enum UI_IPC_SEM e_sp); + +int +ui_ipc_semtrywait(enum UI_IPC_SEM e_sp); + +int +ui_ipc_getvalue(enum UI_IPC_SEM e_sp); + +#ifdef SEM_TIMEDWAIT +int +ui_ipc_semtimedwait(enum UI_IPC_MSQ e_sp, int timeout); +#endif + +int +ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len); + +ssize_t +ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len); + +#endif diff --git a/src/ui_nwindow.c b/src/ui_nwindow.c new file mode 100644 index 0000000..aa1812d --- /dev/null +++ b/src/ui_nwindow.c @@ -0,0 +1,157 @@ +#include +#include + +#include "ui_nwindow.h" + + +struct txtwindow * +init_txtwindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height, chtype attrs, chtype text_attrs, window_func cb_update) +{ + struct txtwindow *a = calloc(1, sizeof(struct txtwindow)); + + a->x = x; + a->y = y; + a->width = width; + a->height = height; + a->active = false; + a->title_len = INITIAL_TITLE_LEN; + a->title = calloc(a->title_len+1, sizeof(char)); + a->text = NULL; + a->attrs = attrs; + a->text_attrs = text_attrs; + a->window_func = cb_update; + return (a); +} + +static void +__free_text(struct txtwindow *a) +{ + if (a->text) { + if (a->text[0]) { + free(a->text[0]); + } + free(a->text); + a->text = NULL; + } +} + +void +free_txtwindow(struct txtwindow *a) +{ + __free_text(a); + if (a->title) { + free(a->title); + } + free(a); +} + +static void +print_wnd(struct txtwindow *a) +{ + int i, x = a->x, y = a->y, w = a->width, h = a->height; + char tmp[a->width+1]; + + attron(a->attrs); + /* print window surface */ + memset(tmp, ' ', a->width); + tmp[a->width] = '\0'; + for (i = y-1; i < y+h+2; i++) + mvprintw(i, x, tmp); + /* print window border */ + mvhline(y-2, x, 0, w); + mvhline(y+h+2, x, 0, w); + mvvline(y-1, x-1, 0, h+3); + mvvline(y-1, x+w, 0, h+3); + /* print window border edges */ + mvaddch(y-2, x-1, ACS_ULCORNER); + mvaddch(y+2+h, x-1, ACS_LLCORNER); + mvaddch(y-2, x+w, ACS_URCORNER); + mvaddch(y+2+h, x+w, ACS_LRCORNER); + /* print window title */ + attroff(a->attrs); + attron(a->text_attrs); + mvprintw(y-2, (float)x+(float)(w/2)-(float)(a->title_len*2/3), "[ %s ]", a->title); + /* print windows text */ + i = 0; + while ( a->text && a->text[i] ) { + mvprintw(y+i, x, a->text[i]); + i++; + } + attroff(a->text_attrs); +} + +static int +txtwindow_cb(WINDOW *win, void *data, bool timedout) +{ + struct txtwindow *a = (struct txtwindow *) data; + + if (a->active == true) { + print_wnd(a); + } + return (UICB_OK); +} + +void inline +register_txtwindow(struct txtwindow *a) +{ + struct ui_callbacks cbs; + cbs.ui_element = txtwindow_cb; + cbs.ui_input = NULL; + register_ui_elt(&cbs, (void *) a, NULL); +} + +static size_t +__do_textcpy(char **p_dest, size_t sz_dest, const char *p_src, size_t sz_src) +{ + size_t cursiz = sz_dest; + + if (sz_src > sz_dest) { + *p_dest = (char *) realloc(*p_dest, (sz_src+1) * sizeof(char)); + cursiz = sz_src; + } + memset(*p_dest, '\0', (cursiz+1) * sizeof(char)); + memcpy(*p_dest, p_src, (cursiz+1) * sizeof(char)); + return sz_src; +} + +/* seperate a String with NEWLINES into an array */ +static char ** +__do_textadjust(struct txtwindow *a, char *text) +{ + int i = 0, rows = (int)(strlen(text) / a->width)+1; + char **adj_text = calloc(rows+1, sizeof(char *)); + char *p_strtok, *tok; + const char sep[] = "\n"; + + if (rows > a->height) goto error; + p_strtok = strdup(text); + while ( (tok = strsep(&p_strtok, sep)) && rows-- >= 0 ) { + if (strlen(tok) > a->width) { + strcpy(tok+a->width-3, "..."); + *(tok+a->width) = '\0'; + } + adj_text[i] = tok; + i++; + } + return adj_text; +error: + free(adj_text); + return NULL; +} + +void +set_txtwindow_text(struct txtwindow *a, char *text) +{ + char **fmt_text = __do_textadjust(a, text); + + if (fmt_text) { + __free_text(a); + a->text = fmt_text; + } +} + +void +set_txtwindow_title(struct txtwindow *a, const char *title) +{ + a->title_len = __do_textcpy(&a->title, a->title_len, title, strlen(title)); +} diff --git a/src/ui_nwindow.h b/src/ui_nwindow.h new file mode 100644 index 0000000..198481b --- /dev/null +++ b/src/ui_nwindow.h @@ -0,0 +1,44 @@ +#ifndef UI_TXTWINDOW_H +#define UI_TXTWINDOW_H 1 + +#include + +#include "ui.h" + +#define INITIAL_TITLE_LEN 32 + +#define set_txtwindow_active(wnd, activate) wnd->active = activate; ui_thrd_force_update() + +struct txtwindow { + unsigned int y; + unsigned int x; + unsigned int width; + unsigned int height; + bool active; + char *title; + size_t title_len; + char **text; + int (*window_func)(WINDOW *, struct txtwindow *); + chtype attrs; + chtype text_attrs; + void *userptr; +}; + +typedef int (*window_func)(WINDOW *, struct txtwindow *); + +struct txtwindow * +init_txtwindow(unsigned int, unsigned int y, unsigned int width, unsigned int height, chtype attrs, chtype text_attrs, window_func cb_update); + +void +free_txtwindow(struct txtwindow *a); + +void +register_txtwindow(struct txtwindow *a); + +void +set_txtwindow_text(struct txtwindow *a, char *text); + +void +set_txtwindow_title(struct txtwindow *a, const char *title); + +#endif diff --git a/src/ui_statusbar.c b/src/ui_statusbar.c new file mode 100644 index 0000000..8fcfeb4 --- /dev/null +++ b/src/ui_statusbar.c @@ -0,0 +1,78 @@ +#include +#include + +#include "ui.h" +#include "ui_statusbar.h" + + +struct statusbar * +init_statusbar(unsigned int y, unsigned int width, chtype attrs, status_func cb_update) +{ + struct statusbar *a = calloc(1, sizeof(struct statusbar)); + + a->y = y; + a->width = width; + a->text = calloc(a->width, sizeof(char)); + a->attrs = attrs; + a->status_func = cb_update; + return (a); +} + +void +free_statusbar(struct statusbar *a) +{ + if (a->text) { + free(a->text); + } + free(a); +} + +int +statusbar_cb(WINDOW *win, void *data, bool timed_out) +{ + struct statusbar *a = (struct statusbar *) data; + char *tmp; + unsigned int diff_pos = 0; + size_t len; + + if (a == NULL) return (UICB_ERR_UNDEF); + if (timed_out == true) { + if (a->status_func != NULL) { + a->status_func(win, a); + } + } + attron(a->attrs); + len = strnlen(a->text, a->width); + if (len < a->width) { + diff_pos = (unsigned int) (a->width - len)/2; + } + tmp = (char *) malloc(a->width + 1); + memset(tmp, ' ', a->width); + tmp[a->width] = '\0'; + strncpy((tmp + diff_pos), a->text, len); + if (win != NULL) { + mvwprintw(win, a->y, 0, tmp); + } else { + mvprintw(a->y, 0, tmp); + } + free(tmp); + attroff(a->attrs); + return (UICB_OK); +} + +void +register_statusbar(struct statusbar *a) +{ + struct ui_callbacks cbs; + cbs.ui_element = statusbar_cb; + cbs.ui_input = NULL; + register_ui_elt(&cbs, (void *) a, NULL); +} + +inline void +set_statusbar_text(struct statusbar *a, const char *text) +{ + size_t len = strlen(text); + + strncpy(a->text, text, (len > a->width ? a->width : len)); +} diff --git a/src/ui_statusbar.h b/src/ui_statusbar.h new file mode 100644 index 0000000..5139c14 --- /dev/null +++ b/src/ui_statusbar.h @@ -0,0 +1,32 @@ +#ifndef UI_STATUSBAR_H +#define UI_STATUSBAR_H 1 + +#include + + +struct statusbar { + unsigned int y; + unsigned int width; + char *text; + int (*status_func)(WINDOW *, struct statusbar *); + chtype attrs; +}; + +typedef int (*status_func)(WINDOW *, struct statusbar *); + +struct statusbar * +init_statusbar(unsigned int y, unsigned int width, chtype attrs, status_func cb_update); + +void +free_statusbar(struct statusbar *a); + +int +statusbar_cb(WINDOW *win, void *data, bool timed_out); + +void +register_statusbar(struct statusbar *a); + +void +set_statusbar_text(struct statusbar *a, const char *text); + +#endif diff --git a/status.c b/status.c deleted file mode 100644 index 5286ddf..0000000 --- a/status.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -#include -#include - -#include "status.h" - - -char * -get_system_stat(void) -{ - char *retstr = NULL; - int ncpu; - struct sysinfo inf; - - if (sysinfo(&inf) == EFAULT) { - return ("[SYSINFO ERROR]"); - } - ncpu = get_nprocs(); - - if (asprintf(&retstr, "u:%04ld - l:%3.2f,%3.2f,%3.2f - %dcore%s - mem:%lu/%lumb - procs:%02d", - inf.uptime, ((float)inf.loads[0]/10000), ((float)inf.loads[1]/10000), ((float)inf.loads[2]/10000), - ncpu, (ncpu > 1 ? "s" : ""), - (unsigned long)((inf.freeram/1024)/1024), (unsigned long)((inf.totalram/1024)/1024), inf.procs) == -1) { - return ("[ASPRINTF ERROR]"); - } - return (retstr); -} diff --git a/status.h b/status.h deleted file mode 100644 index 995d08a..0000000 --- a/status.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef STATUS_H -#define STATUS_H 1 - -char * -get_system_stat(void); - -#endif diff --git a/tests/Makefile b/tests/Makefile index 436d00f..20b86ba 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,7 +8,7 @@ DEPS = $(patsubst %.c,%.d,$(SOURCES)) all: $(BINARIES) semtest2: - $(CC) $(CFLAGS) $(LDFLAGS) ../ui_ipc.o semtest2.c -o semtest2 + $(CC) $(CFLAGS) $(LDFLAGS) -I ../src ../src/ui_ipc.o semtest2.c -o semtest2 %: %.c $(CC) $(CFLAGS) $(LDFLAGS) $< -o $(patsubst %.c,%,$<) diff --git a/tests/semtest2.c b/tests/semtest2.c index c015df8..1724cf1 100644 --- a/tests/semtest2.c +++ b/tests/semtest2.c @@ -7,7 +7,7 @@ #include #include -#include "../ui_ipc.h" +#include "ui_ipc.h" pid_t child; diff --git a/ui.c b/ui.c deleted file mode 100644 index 457d76d..0000000 --- a/ui.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ui.h" -#include "ui_ipc.h" -#include "ui_elements.h" -#include "ui_ani.h" -#include "ui_input.h" -#include "ui_statusbar.h" -#include "ui_nwindow.h" - -#include "status.h" -#include "config.h" - -#define APP_TIMEOUT 60 -#define APP_TIMEOUT_FMT "%02d" -#define PASSWD_WIDTH 35 -#define PASSWD_HEIGHT 5 -#define PASSWD_XRELPOS (unsigned int)(PASSWD_WIDTH / 2) - (PASSWD_WIDTH / 6) -#define PASSWD_YRELPOS (unsigned int)(PASSWD_HEIGHT / 2) + 1 -#define INFOWND_WIDTH 25 -#define INFOWND_HEIGHT 3 -#define INFOWND_XRELPOS (unsigned int)(INFOWND_WIDTH / 2) - (INFOWND_WIDTH / 6) -#define INFOWND_YRELPOS (unsigned int)(INFOWND_HEIGHT / 2) + 1 - -#define STRLEN(s) (sizeof(s)/sizeof(s[0])) - - -static unsigned int max_x, max_y; -static WINDOW *wnd_main; -static struct nask_ui /* simple linked list to all UI objects */ *nui = NULL, - /* current active input */ *active = NULL; -static pthread_t thrd; -static unsigned int atmout = APP_TIMEOUT; -static pthread_cond_t cnd_update = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t mtx_update = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t mtx_busy = PTHREAD_MUTEX_INITIALIZER; - - -void -register_ui_elt(struct ui_callbacks *cbs, void *data, WINDOW *wnd) -{ - struct nask_ui *tmp, *new; - - new = calloc(1, sizeof(struct nask_ui)); - new->cbs = *cbs; - new->wnd = wnd; - new->data = data; - new->next = NULL; - if (nui == NULL) { - nui = new; - nui->next = NULL; - } else { - tmp = nui; - while (tmp->next != NULL) { - tmp = tmp->next; - } - tmp->next = new; - } -} - -void -unregister_ui_elt(void *data) -{ - struct nask_ui *cur, *next, *before = NULL; - - cur = nui; - while (cur != NULL) { - next = cur->next; - if (cur->data != NULL && cur->data == data) { - free(cur); - if (before != NULL) { - before->next = next; - } else { - nui = next; - } - } - before = cur; - cur = next; - } -} - -int -activate_ui_input(void *data) -{ - struct nask_ui *cur = nui; - - if (cur == NULL || data == NULL) return DOUI_NINIT; - while ( cur->data != NULL ) { - if ( cur->data == data ) { - if ( cur->cbs.ui_input != NULL && cur->cbs.ui_input(cur->wnd, data, UIKEY_ACTIVATE) == DOUI_OK ) { - active = cur; - return DOUI_OK; - } - } - cur = cur->next; - } - return DOUI_ERR; -} - -static bool -process_key(char key) -{ - atmout = APP_TIMEOUT; - if ( active != NULL ) { - return ( active->cbs.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false ); - } - return false; -} - -static int -do_ui_update(bool timed_out) -{ - int retval = UICB_OK; - int curx = getcurx(wnd_main); - int cury = getcury(wnd_main); - struct nask_ui *cur = nui; - - /* call all draw callback's */ - erase(); - while (cur != NULL) { - if (cur->cbs.ui_element != NULL) { - cur->cbs.ui_element(cur->wnd, cur->data, timed_out); - doupdate(); - } else { - retval = UICB_ERR_CB; - } - cur = cur->next; - } - /* TODO: Maybe export to an extra module? */ - attron(COLOR_PAIR(1)); - mvprintw(0, max_x - STRLEN(APP_TIMEOUT_FMT), "[" APP_TIMEOUT_FMT "]", atmout); - attroff(COLOR_PAIR(1)); - /* EoT (End of Todo) */ - wmove(wnd_main, cury, curx); - wrefresh(wnd_main); - return (retval); -} - -static void * -ui_thrd(void *arg) -{ - int cnd_ret; - struct timeval now; - struct timespec wait; - - gettimeofday(&now, NULL); - wait.tv_sec = now.tv_sec + UILOOP_TIMEOUT; - wait.tv_nsec = now.tv_usec * 1000; - do_ui_update(true); - ui_ipc_sempost(SEM_RD); - pthread_mutex_lock(&mtx_update); - while ( ui_ipc_getvalue(SEM_UI) > 0 ) { - pthread_mutex_unlock(&mtx_busy); - cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &wait); - pthread_mutex_lock(&mtx_busy); - if (--atmout == 0) ui_ipc_semtrywait(SEM_UI); - do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) ); - if (cnd_ret == ETIMEDOUT) { - wait.tv_sec += UILOOP_TIMEOUT; - } - } - pthread_mutex_unlock(&mtx_update); - return (NULL); -} - -void -ui_thrd_force_update(void) -{ - pthread_mutex_lock(&mtx_update); - pthread_mutex_lock(&mtx_busy); - pthread_cond_signal(&cnd_update); - pthread_mutex_unlock(&mtx_busy); - pthread_mutex_unlock(&mtx_update); -} - -WINDOW * -init_ui(void) -{ - wnd_main = initscr(); - max_x = getmaxx(wnd_main); - max_y = getmaxy(wnd_main); - start_color(); - init_pair(1, COLOR_RED, COLOR_WHITE); - init_pair(2, COLOR_WHITE, COLOR_BLACK); - init_pair(3, COLOR_BLACK, COLOR_WHITE); - init_pair(4, COLOR_YELLOW, COLOR_RED); - raw(); - keypad(stdscr, TRUE); - noecho(); - cbreak(); - return (wnd_main); -} - -void -free_ui(void) -{ - delwin(wnd_main); - endwin(); - clear(); - printf(" \033[2J\n"); -} - -static int -run_ui_thrd(void) { - return (pthread_create(&thrd, NULL, &ui_thrd, NULL)); -} - -static int -stop_ui_thrd(void) -{ - return (pthread_join(thrd, NULL)); -} - -int -do_ui(void) -{ - char key = '\0'; - char *title = NULL; - int ret = DOUI_ERR; - - asprintf(&title, "/* %s-%s */", PKGNAME, VERSION); - /* init TUI and UI Elements (input field, status bar, etc) */ - init_ui(); - init_ui_elements(wnd_main, max_x, max_y); - - pthread_mutex_lock(&mtx_update); - if (run_ui_thrd() != 0) { - goto error; - } - ui_ipc_semwait(SEM_RD); - wtimeout(wnd_main, 1000); - pthread_mutex_unlock(&mtx_update); - while ( ui_ipc_getvalue(SEM_UI) > 0 ) { - if ((key = wgetch(wnd_main)) == '\0') { - break; - } - if (key == -1) { - continue; - } - if ( process_key(key) != true ) { -// break; - } -// do_ui_update(false); - } - stop_ui_thrd(); - free_ui_elements(); - - ret = DOUI_OK; -error: - if (title) free(title); - title = NULL; - return ret; -} - diff --git a/ui.h b/ui.h deleted file mode 100644 index 91d5403..0000000 --- a/ui.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef UI_H -#define UI_H 1 - -#include -#include - -#define UICB_OK 0 -#define UICB_ERR_UNDEF 1 -#define UICB_ERR_CB 2 -#define UICB_ERR_BUF 3 - -#define DOUI_OK 0 -#define DOUI_ERR 1 -#define DOUI_TMOUT 2 -#define DOUI_NINIT 3 - -#define UILOOP_TIMEOUT 1 - -#define UIKEY_ACTIVATE 0 -#define UIKEY_ENTER 10 -#define UIKEY_BACKSPACE 7 -#define UIKEY_ESC 27 -#define UIKEY_DOWN 2 -#define UIKEY_UP 3 -#define UIKEY_LEFT 4 -#define UIKEY_RIGHT 5 - - -typedef int (*uicb_base)(WINDOW *, void *, bool); -typedef int (*uicb_input)(WINDOW *, void *, int); - - -struct ui_callbacks { - uicb_base ui_element; - uicb_input ui_input; -}; - -struct nask_ui { - struct ui_callbacks cbs; - WINDOW *wnd; - void *data; - struct nask_ui *next; -}; - -void -register_ui_elt(struct ui_callbacks *cbs, void *data, WINDOW *wnd); - -void -unregister_ui_elt(void *data); - -int -activate_ui_input(void *data); - -void -ui_thrd_force_update(void); - -WINDOW * -init_ui(void); - -void -free_ui(void); - -int -do_ui(void); - -#endif diff --git a/ui_ani.c b/ui_ani.c deleted file mode 100644 index c18ad4b..0000000 --- a/ui_ani.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "ui.h" -#include "ui_ani.h" - -#define ANIC_INITSTATE '|' - - -struct anic * -init_anic(unsigned int x, unsigned int y, chtype attrs, char *fmt) -{ - struct anic *a = calloc(1, sizeof(struct anic)); - - a->x = x; - a->y = y; - a->state = ANIC_INITSTATE; - a->attrs = attrs; - if (fmt != NULL) { - a->fmt = strdup(fmt); - } - return (a); -} - -void -free_anic(struct anic *a) -{ - if (a->fmt != NULL) { - free(a->fmt); - } - free(a); -} - -int -anic_cb(WINDOW *win, void *data, bool timed_out) -{ - struct anic *a = (struct anic *) data; - char *tmp; - int retval = UICB_OK; - - if (a == NULL) return (UICB_ERR_UNDEF); - if (timed_out == true) { - switch (a->state) { - default: - case '|': a->state = '/'; break; - case '/': a->state = '-'; break; - case '-': a->state = '\\'; break; - case '\\': a->state = '|'; break; - } - } - attron(a->attrs); - if (a->fmt != NULL) { - if (asprintf(&tmp, a->fmt, a->state) <= 0) { - retval = UICB_ERR_BUF; - } - } else { - asprintf(&tmp, "%c", a->state); - } - if (win != NULL) { - mvwprintw(win, a->y, a->x, tmp); - } else { - mvprintw(a->y, a->x, tmp); - } - free(tmp); - attroff(a->attrs); - return (retval); -} - -void -register_anic(struct anic *a) -{ - struct ui_callbacks cbs; - cbs.ui_element = anic_cb; - cbs.ui_input = NULL; - register_ui_elt(&cbs, (void *) a, NULL); -} diff --git a/ui_ani.h b/ui_ani.h deleted file mode 100644 index 15962ae..0000000 --- a/ui_ani.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef UI_ANIC_H -#define UI_ANIC_H 1 - -#include - - -struct anic { - unsigned int x; - unsigned int y; - char state; - char *fmt; - chtype attrs; -}; - -struct anic * -init_anic(unsigned int x, unsigned int y, chtype attrs, char *fmt); - -void -free_anic(struct anic *a); - -int -anic_cb(WINDOW *win, void *data, bool timed_out); - -void -register_anic(struct anic *a); - -#endif diff --git a/ui_elements.c b/ui_elements.c deleted file mode 100644 index 0633b42..0000000 --- a/ui_elements.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include - -#include "ui.h" -#include "ui_ipc.h" -#include "ui_ani.h" -#include "ui_input.h" -#include "ui_statusbar.h" -#include "ui_nwindow.h" -#include "ui_elements.h" - -#include "status.h" - -#define PASSWD_WIDTH 35 -#define PASSWD_HEIGHT 5 -#define PASSWD_XRELPOS (unsigned int)(PASSWD_WIDTH / 2) - (PASSWD_WIDTH / 6) -#define PASSWD_YRELPOS (unsigned int)(PASSWD_HEIGHT / 2) + 1 -#define INFOWND_WIDTH 25 -#define INFOWND_HEIGHT 3 -#define INFOWND_XRELPOS (unsigned int)(INFOWND_WIDTH / 2) - (INFOWND_WIDTH / 6) -#define INFOWND_YRELPOS (unsigned int)(INFOWND_HEIGHT / 2) + 1 - -static struct input *pw_input; -static struct anic *heartbeat; -static struct statusbar *higher, *lower; -static struct txtwindow *infownd; -static char *title = NULL; - - -static int -lower_statusbar_update(WINDOW *win, struct statusbar *bar) -{ - char *tmp = get_system_stat(); - set_statusbar_text(bar, tmp); - free(tmp); - return 0; -} - -static int -higher_statusbar_update(WINDOW *win, struct statusbar *bar) -{ - return 0; -} - -static int -infownd_update(WINDOW *win, struct txtwindow *tw) -{ - char *tmp = (char*)(tw->userptr); - size_t len = strlen(tmp); - - if (tw->active) { - if ( len == 3 ) { - memset(tmp+1, '\0', 2); - } else strcat(tmp, "."); - } else (*tmp) = '.'; - return 0; -} - -static int -mq_passwd_send(char *passwd, size_t len) -{ - int ret; - - ui_ipc_sempost(SEM_IN); - ret = ui_ipc_msgsend(MQ_PW, passwd, len); - memset(passwd, '\0', len); - return ret; -} - -static int -passwd_input_cb(WINDOW *wnd, void *data, int key) -{ - struct input *a = (struct input *) data; -/* - * if ( process_key(key, pw_input, wnd_main) == false ) { - * curs_set(0); - * memset(mq_msg, '\0', IPC_MQSIZ+1); - * mq_receive(mq_info, mq_msg, IPC_MQSIZ+1, 0); - * set_txtwindow_text(infownd, mq_msg); - * set_txtwindow_active(infownd, true); - * sleep(3); - * sem_trywait(sp_ui); - * } - * activate_input(wnd_main, pw_input); - */ - switch (key) { - case UIKEY_ENTER: - mq_passwd_send(a->input, a->input_len); - memset(a->input, '\0', a->input_len); - a->input_len = 0; - a->input_pos = 0; - a->cur_pos = 0; - ui_thrd_force_update(); - break; - case UIKEY_BACKSPACE: - del_input(wnd, a); - break; - case UIKEY_ESC: - return DOUI_ERR; - break; - case UIKEY_DOWN: - case UIKEY_UP: - case UIKEY_LEFT: - case UIKEY_RIGHT: - break; - case UIKEY_ACTIVATE: - break; - default: - add_input(wnd, a, key); - } - return DOUI_OK; -} - -void -init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y) -{ - asprintf(&title, "/* %s-%s */", PKGNAME, VERSION); - pw_input = init_input((unsigned int)(max_x / 2)-PASSWD_XRELPOS, (unsigned int)(max_y / 2)-PASSWD_YRELPOS, PASSWD_WIDTH, "PASSWORD: ", IPC_MQSIZ, COLOR_PAIR(3), COLOR_PAIR(2)); - heartbeat = init_anic(0, 0, A_BOLD | COLOR_PAIR(1), "[%c]"); - higher = init_statusbar(0, max_x, A_BOLD | COLOR_PAIR(3), higher_statusbar_update); - lower = init_statusbar(max_y - 1, max_x, COLOR_PAIR(3), lower_statusbar_update); - infownd = init_txtwindow((unsigned int)(max_x / 2)-INFOWND_XRELPOS, (unsigned int)(max_y / 2)-INFOWND_YRELPOS, INFOWND_WIDTH, INFOWND_HEIGHT, COLOR_PAIR(4), COLOR_PAIR(4) | A_BOLD, infownd_update); - infownd->userptr = calloc(4, sizeof(char)); - (*(char*)(infownd->userptr)) = '.'; - - register_input(NULL, pw_input, passwd_input_cb); - register_statusbar(higher); - register_statusbar(lower); - register_anic(heartbeat); - register_txtwindow(infownd); - set_txtwindow_title(infownd, "WARNING"); - activate_input(wnd_main, pw_input); - set_statusbar_text(higher, title); -} - -void -free_ui_elements(void) -{ - unregister_ui_elt(lower); - unregister_ui_elt(higher); - unregister_ui_elt(heartbeat); - unregister_ui_elt(pw_input); - free_input(pw_input); - free_anic(heartbeat); - free_statusbar(higher); - free_statusbar(lower); - free(infownd->userptr); - free_txtwindow(infownd); - free_ui(); -} diff --git a/ui_elements.h b/ui_elements.h deleted file mode 100644 index 0cf8826..0000000 --- a/ui_elements.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef UI_ELEMENTS_H -#define UI_ELEMENTS_H 1 - -#include "config.h" - - -void -init_ui_elements(WINDOW *wnd_main, unsigned int max_x, unsigned int max_y); - -void -free_ui_elements(void); - -#endif diff --git a/ui_input.c b/ui_input.c deleted file mode 100644 index 9b70f81..0000000 --- a/ui_input.c +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include - -#include "ui.h" -#include "ui_input.h" - - -struct input * -init_input(unsigned int x, unsigned int y, unsigned int width, char *prompt, size_t input_len, chtype attrs, chtype shadow) -{ - struct input *a = calloc(1, sizeof(struct input)); - - a->x = x; - a->y = y; - a->width = width; - a->cur_pos = 0; - a->input = calloc(input_len+1, sizeof(char)); - a->input_max = input_len; - a->input_len = 0; - a->input_pos = 0; - a->prompt = strdup(prompt); - a->attrs = attrs; - a->shadow = shadow; - return (a); -} - -void -free_input(struct input *a) -{ - if (a->input != NULL) { - free(a->input); - } - free(a->prompt); - free(a); -} - -static void -print_wnd(size_t addwidth, struct input *a) -{ - int i, x = a->x, y = a->y; - size_t relwidth = addwidth*2, len = strlen(a->prompt) + a->width; - char tmp[len+relwidth+1]; - - attron(a->attrs); - memset(tmp, ' ', len+relwidth); - tmp[len+relwidth] = '\0'; - for (i = -1; i <= 1; i++) - mvprintw(y+i, x-addwidth, tmp); - - mvhline(y-2, x-addwidth, 0, len+relwidth); - mvhline(y+2, x-addwidth, 0, len+relwidth); - mvvline(y-1, x-addwidth-1, 0, 3); - mvvline(y-1, x+len+addwidth, 0, 3); - mvaddch(y-2, x-addwidth-1, ACS_ULCORNER); - mvaddch(y+2, x-addwidth-1, ACS_LLCORNER); - mvaddch(y-2, x+len+addwidth, ACS_URCORNER); - mvaddch(y+2, x+len+addwidth, ACS_LRCORNER); - attroff(a->attrs); - - attron(a->shadow); - for (i = x-addwidth+1; i < x+len+relwidth; i++) - mvaddch(y+3, i, ACS_CKBOARD); - for (i = -1; i < 3; i++) { - mvaddch(y+i, x+len+relwidth-2, ACS_CKBOARD); - mvaddch(y+i, x+len+relwidth-1, ACS_CKBOARD); - } - attroff(a->shadow); -} - -static void -print_input_text(WINDOW *win, struct input *a) -{ - size_t start = 0; - size_t p_len = strlen(a->prompt); - - char tmp[a->width + 1]; - memset(tmp, '\0', a->width + 1); - if (a->input_pos >= a->width) { - start = a->input_pos - a->width; - } - - strncpy(tmp, (char *)(a->input + start), a->width); - int i; - for (i = 0; i < strlen(tmp); i++) { - tmp[i] = '*'; - } - - if (win == NULL) { - mvprintw(a->y, a->x + p_len, "%s", tmp); - } else { - mvwprintw(win, a->y, a->x + p_len, "%s", tmp); - } -} - -static void -print_input(WINDOW *win, struct input *a) -{ - char *tmp; - int i; - size_t p_len = strlen(a->prompt); - - print_wnd(3, a); - attron(a->attrs); - if (win) { - mvwprintw(win, a->y, a->x, a->prompt); - } else { - mvprintw(a->y, a->x, a->prompt); - } - tmp = calloc(a->width+1, sizeof(char)); - for (i = 0; i < a->width; i++) { - *(tmp + i) = '_'; - } - if (win) { - mvwprintw(win, a->y, a->x + p_len, tmp); - } else { - mvprintw(a->y, a->x + p_len, tmp); - } - free(tmp); - print_input_text(win, a); - attroff(a->attrs); -} - -int -activate_input(WINDOW *win, struct input *a) -{ - if (a == NULL) return (UICB_ERR_UNDEF); - size_t p_len = strlen(a->prompt); - if (win == NULL) { - move(a->y, a->x + p_len + a->cur_pos); - } else { - wmove(win, a->y, a->x + p_len + a->cur_pos); - } - return (activate_ui_input( (void *) a )); -} - -int -add_input(WINDOW *win, struct input *a, int key) -{ - if (a == NULL) return (UICB_ERR_UNDEF); - if (a->input_len >= a->input_max) return (UICB_ERR_BUF); - *(a->input + a->input_pos) = (char) key; - ++a->input_pos; - ++a->input_len; - a->cur_pos = (a->cur_pos+1 < a->width ? a->cur_pos+1 : a->cur_pos); - print_input(win, a); - return (UICB_OK); -} - -int -del_input(WINDOW *win, struct input *a) -{ - if (a == NULL) return (UICB_ERR_UNDEF); - if (a->input_len == 0) return (UICB_ERR_BUF); - memmove((a->input + a->input_pos - 1), (a->input + a->input_pos), a->input_max - a->input_pos); - --a->input_len; - *(a->input + a->input_len) = '\0'; - if (a->input_pos-1 == a->input_len) { - --a->input_pos; - } - if (a->cur_pos+1 < a->width && a->cur_pos > 0) { - --a->cur_pos; - } else if (a->cur_pos-1 == a->input_pos) { - --a->cur_pos; - } - mvwprintw(win, a->y, a->x + a->cur_pos + strlen(a->prompt), "_"); - print_input(win, a); - return (UICB_OK); -} - -static int -input_cb(WINDOW *win, void *data, bool timed_out) -{ - struct input *a = (struct input *) data; - - if (a == NULL) return (UICB_ERR_UNDEF); - if (win != NULL && is_wintouched(win) == false) return (UICB_OK); - print_input(win, a); - return (UICB_OK); -} - -void -register_input(WINDOW *win, struct input *a, uicb_input ipcb) -{ - struct ui_callbacks cbs; - cbs.ui_element = input_cb; - cbs.ui_input = ipcb; - register_ui_elt(&cbs, (void *) a, win); -} - diff --git a/ui_input.h b/ui_input.h deleted file mode 100644 index 5407616..0000000 --- a/ui_input.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef UI_INPUT_H -#define UI_INPUT_H 1 - -#include - - -struct input { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int cur_pos; - char *input; - size_t input_max; - size_t input_len; - size_t input_pos; - char *prompt; - chtype attrs; - chtype shadow; - uicb_input cb_input; -}; - -struct input * -init_input(unsigned int x, unsigned int y, unsigned int width, char *prompt, size_t input_len, chtype attrs, chtype shadow); - -void -free_input(struct input *a); - -int -activate_input(WINDOW *win, struct input *a); - -int -add_input(WINDOW *win, struct input *a, int key); - -int -del_input(WINDOW *win, struct input *a); - -void -register_input(WINDOW *win, struct input *a, uicb_input ipcb); - -void -unregister_input(struct input *a); - -#endif diff --git a/ui_ipc.c b/ui_ipc.c deleted file mode 100644 index 60da7cb..0000000 --- a/ui_ipc.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#ifdef SEM_TIMEDWAIT -#include -#endif -#include -#include -#include -#include - -#include "ui_ipc.h" - -#define JMP_IF(cmd, retval, jmplabel) if ( (cmd) == retval ) { printf("(%s) == %p\n", #cmd, (void*)retval); goto jmplabel; } - - -static sem_t *sems[SEM_NUM]; -static mqd_t msqs[MSQ_NUM]; -static unsigned char initialized = 0; - - -int -ui_ipc_init(int is_master) -{ - volatile int sp_oflags, mq_oflags; - mode_t crt_flags; - struct mq_attr m_attr; - - if (initialized) { - return -1; - } - bzero(sems, sizeof(sem_t*)*SEM_NUM); - bzero(msqs, sizeof(mqd_t)*MSQ_NUM); - m_attr.mq_flags = 0; - m_attr.mq_msgsize = IPC_MQSIZ; - m_attr.mq_maxmsg = 3; - m_attr.mq_curmsgs = 0; - if (is_master) { - sp_oflags = O_CREAT | O_EXCL; - mq_oflags = O_NONBLOCK | O_CREAT | O_EXCL; - crt_flags = S_IRUSR | S_IWUSR; - JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); - JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); - } else { - sp_oflags = 0; - mq_oflags = 0; - crt_flags = 0; - JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error ); - JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error ); - } - JMP_IF( sems[SEM_UI] = sem_open(SEM_GUI, sp_oflags, crt_flags, 0), SEM_FAILED, error ); - JMP_IF( sems[SEM_IN] = sem_open(SEM_INP, sp_oflags, crt_flags, 0), SEM_FAILED, error ); - JMP_IF( sems[SEM_BS] = sem_open(SEM_BSY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); - JMP_IF( sems[SEM_RD] = sem_open(SEM_RDY, sp_oflags, crt_flags, 0), SEM_FAILED, error ); - initialized = 1; - return 0; -error: - return errno; -} - -void -ui_ipc_free(int is_master) -{ - int i; - - if (!initialized) { - return; - } - for (i = 0; i < SEM_NUM; i++) { - if (sems[i]) sem_close(sems[i]); - } - for (i = 0; i < MSQ_NUM; i++) { - if (msqs[i]) mq_close(msqs[i]); - } - if (is_master > 0) { - sem_unlink(SEM_BSY); - sem_unlink(SEM_GUI); - sem_unlink(SEM_INP); - sem_unlink(SEM_RDY); - mq_unlink(MSQ_PWD); - mq_unlink(MSQ_INF); - } - initialized = 0; -} - -int -ui_ipc_sempost(enum UI_IPC_SEM e_sp) -{ - return ( sem_post(sems[e_sp]) ); -} - -int -ui_ipc_semwait(enum UI_IPC_SEM e_sp) -{ - return ( sem_wait(sems[e_sp]) ); -} - -int -ui_ipc_semtrywait(enum UI_IPC_SEM e_sp) -{ - return ( sem_trywait(sems[e_sp]) ); -} - -int -ui_ipc_getvalue(enum UI_IPC_SEM e_sp) -{ - int sp_val = 0; - - if (sem_getvalue(sems[e_sp], &sp_val) != 0) { - return -1; - } - return sp_val; -} - -#ifdef SEM_TIMEDWAIT -int -ui_ipc_semtimedwait(enum UI_IPC_SEM e_sp, int timeout) -{ - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { - return -1; - } - ts.tc_sec += timeout; - return ( sem_timedwait(sems[q_mq], &ts) ); -} -#endif - -int -ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len) -{ - return ( mq_send(msqs[e_mq], msg_ptr, msg_len, 0) ); -} - -ssize_t -ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len) -{ - return ( mq_receive(msqs[e_mq], msg_ptr, msg_len, NULL) ); -} - diff --git a/ui_ipc.h b/ui_ipc.h deleted file mode 100644 index 2c5bcb5..0000000 --- a/ui_ipc.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef UI_IPC_H -#define UI_IPC_H 1 - -#include "status.h" -#include "config.h" - - -enum UI_IPC_SEM { - SEM_RD = 0, /* UI Init done? */ - SEM_UI, /* TUI active? */ - SEM_IN, /* Textfield has input avail */ - SEM_BS, /* Master process busy */ - SEM_NUM -}; - -enum UI_IPC_MSQ { - MQ_PW = 0, - MQ_IF, - MSQ_NUM -}; - - -int -ui_ipc_init(int is_master); - -void -ui_ipc_free(int is_master); - -int -ui_ipc_sempost(enum UI_IPC_SEM e_sp); - -int -ui_ipc_semwait(enum UI_IPC_SEM e_sp); - -int -ui_ipc_semtrywait(enum UI_IPC_SEM e_sp); - -int -ui_ipc_getvalue(enum UI_IPC_SEM e_sp); - -#ifdef SEM_TIMEDWAIT -int -ui_ipc_semtimedwait(enum UI_IPC_MSQ e_sp, int timeout); -#endif - -int -ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr, size_t msg_len); - -ssize_t -ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, size_t msg_len); - -#endif diff --git a/ui_nwindow.c b/ui_nwindow.c deleted file mode 100644 index aa1812d..0000000 --- a/ui_nwindow.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include - -#include "ui_nwindow.h" - - -struct txtwindow * -init_txtwindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height, chtype attrs, chtype text_attrs, window_func cb_update) -{ - struct txtwindow *a = calloc(1, sizeof(struct txtwindow)); - - a->x = x; - a->y = y; - a->width = width; - a->height = height; - a->active = false; - a->title_len = INITIAL_TITLE_LEN; - a->title = calloc(a->title_len+1, sizeof(char)); - a->text = NULL; - a->attrs = attrs; - a->text_attrs = text_attrs; - a->window_func = cb_update; - return (a); -} - -static void -__free_text(struct txtwindow *a) -{ - if (a->text) { - if (a->text[0]) { - free(a->text[0]); - } - free(a->text); - a->text = NULL; - } -} - -void -free_txtwindow(struct txtwindow *a) -{ - __free_text(a); - if (a->title) { - free(a->title); - } - free(a); -} - -static void -print_wnd(struct txtwindow *a) -{ - int i, x = a->x, y = a->y, w = a->width, h = a->height; - char tmp[a->width+1]; - - attron(a->attrs); - /* print window surface */ - memset(tmp, ' ', a->width); - tmp[a->width] = '\0'; - for (i = y-1; i < y+h+2; i++) - mvprintw(i, x, tmp); - /* print window border */ - mvhline(y-2, x, 0, w); - mvhline(y+h+2, x, 0, w); - mvvline(y-1, x-1, 0, h+3); - mvvline(y-1, x+w, 0, h+3); - /* print window border edges */ - mvaddch(y-2, x-1, ACS_ULCORNER); - mvaddch(y+2+h, x-1, ACS_LLCORNER); - mvaddch(y-2, x+w, ACS_URCORNER); - mvaddch(y+2+h, x+w, ACS_LRCORNER); - /* print window title */ - attroff(a->attrs); - attron(a->text_attrs); - mvprintw(y-2, (float)x+(float)(w/2)-(float)(a->title_len*2/3), "[ %s ]", a->title); - /* print windows text */ - i = 0; - while ( a->text && a->text[i] ) { - mvprintw(y+i, x, a->text[i]); - i++; - } - attroff(a->text_attrs); -} - -static int -txtwindow_cb(WINDOW *win, void *data, bool timedout) -{ - struct txtwindow *a = (struct txtwindow *) data; - - if (a->active == true) { - print_wnd(a); - } - return (UICB_OK); -} - -void inline -register_txtwindow(struct txtwindow *a) -{ - struct ui_callbacks cbs; - cbs.ui_element = txtwindow_cb; - cbs.ui_input = NULL; - register_ui_elt(&cbs, (void *) a, NULL); -} - -static size_t -__do_textcpy(char **p_dest, size_t sz_dest, const char *p_src, size_t sz_src) -{ - size_t cursiz = sz_dest; - - if (sz_src > sz_dest) { - *p_dest = (char *) realloc(*p_dest, (sz_src+1) * sizeof(char)); - cursiz = sz_src; - } - memset(*p_dest, '\0', (cursiz+1) * sizeof(char)); - memcpy(*p_dest, p_src, (cursiz+1) * sizeof(char)); - return sz_src; -} - -/* seperate a String with NEWLINES into an array */ -static char ** -__do_textadjust(struct txtwindow *a, char *text) -{ - int i = 0, rows = (int)(strlen(text) / a->width)+1; - char **adj_text = calloc(rows+1, sizeof(char *)); - char *p_strtok, *tok; - const char sep[] = "\n"; - - if (rows > a->height) goto error; - p_strtok = strdup(text); - while ( (tok = strsep(&p_strtok, sep)) && rows-- >= 0 ) { - if (strlen(tok) > a->width) { - strcpy(tok+a->width-3, "..."); - *(tok+a->width) = '\0'; - } - adj_text[i] = tok; - i++; - } - return adj_text; -error: - free(adj_text); - return NULL; -} - -void -set_txtwindow_text(struct txtwindow *a, char *text) -{ - char **fmt_text = __do_textadjust(a, text); - - if (fmt_text) { - __free_text(a); - a->text = fmt_text; - } -} - -void -set_txtwindow_title(struct txtwindow *a, const char *title) -{ - a->title_len = __do_textcpy(&a->title, a->title_len, title, strlen(title)); -} diff --git a/ui_nwindow.h b/ui_nwindow.h deleted file mode 100644 index 198481b..0000000 --- a/ui_nwindow.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef UI_TXTWINDOW_H -#define UI_TXTWINDOW_H 1 - -#include - -#include "ui.h" - -#define INITIAL_TITLE_LEN 32 - -#define set_txtwindow_active(wnd, activate) wnd->active = activate; ui_thrd_force_update() - -struct txtwindow { - unsigned int y; - unsigned int x; - unsigned int width; - unsigned int height; - bool active; - char *title; - size_t title_len; - char **text; - int (*window_func)(WINDOW *, struct txtwindow *); - chtype attrs; - chtype text_attrs; - void *userptr; -}; - -typedef int (*window_func)(WINDOW *, struct txtwindow *); - -struct txtwindow * -init_txtwindow(unsigned int, unsigned int y, unsigned int width, unsigned int height, chtype attrs, chtype text_attrs, window_func cb_update); - -void -free_txtwindow(struct txtwindow *a); - -void -register_txtwindow(struct txtwindow *a); - -void -set_txtwindow_text(struct txtwindow *a, char *text); - -void -set_txtwindow_title(struct txtwindow *a, const char *title); - -#endif diff --git a/ui_statusbar.c b/ui_statusbar.c deleted file mode 100644 index 8fcfeb4..0000000 --- a/ui_statusbar.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "ui.h" -#include "ui_statusbar.h" - - -struct statusbar * -init_statusbar(unsigned int y, unsigned int width, chtype attrs, status_func cb_update) -{ - struct statusbar *a = calloc(1, sizeof(struct statusbar)); - - a->y = y; - a->width = width; - a->text = calloc(a->width, sizeof(char)); - a->attrs = attrs; - a->status_func = cb_update; - return (a); -} - -void -free_statusbar(struct statusbar *a) -{ - if (a->text) { - free(a->text); - } - free(a); -} - -int -statusbar_cb(WINDOW *win, void *data, bool timed_out) -{ - struct statusbar *a = (struct statusbar *) data; - char *tmp; - unsigned int diff_pos = 0; - size_t len; - - if (a == NULL) return (UICB_ERR_UNDEF); - if (timed_out == true) { - if (a->status_func != NULL) { - a->status_func(win, a); - } - } - attron(a->attrs); - len = strnlen(a->text, a->width); - if (len < a->width) { - diff_pos = (unsigned int) (a->width - len)/2; - } - tmp = (char *) malloc(a->width + 1); - memset(tmp, ' ', a->width); - tmp[a->width] = '\0'; - strncpy((tmp + diff_pos), a->text, len); - if (win != NULL) { - mvwprintw(win, a->y, 0, tmp); - } else { - mvprintw(a->y, 0, tmp); - } - free(tmp); - attroff(a->attrs); - return (UICB_OK); -} - -void -register_statusbar(struct statusbar *a) -{ - struct ui_callbacks cbs; - cbs.ui_element = statusbar_cb; - cbs.ui_input = NULL; - register_ui_elt(&cbs, (void *) a, NULL); -} - -inline void -set_statusbar_text(struct statusbar *a, const char *text) -{ - size_t len = strlen(text); - - strncpy(a->text, text, (len > a->width ? a->width : len)); -} diff --git a/ui_statusbar.h b/ui_statusbar.h deleted file mode 100644 index 5139c14..0000000 --- a/ui_statusbar.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef UI_STATUSBAR_H -#define UI_STATUSBAR_H 1 - -#include - - -struct statusbar { - unsigned int y; - unsigned int width; - char *text; - int (*status_func)(WINDOW *, struct statusbar *); - chtype attrs; -}; - -typedef int (*status_func)(WINDOW *, struct statusbar *); - -struct statusbar * -init_statusbar(unsigned int y, unsigned int width, chtype attrs, status_func cb_update); - -void -free_statusbar(struct statusbar *a); - -int -statusbar_cb(WINDOW *win, void *data, bool timed_out); - -void -register_statusbar(struct statusbar *a); - -void -set_statusbar_text(struct statusbar *a, const char *text); - -#endif -- cgit v1.2.3