aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoni <matzeton@googlemail.com>2016-07-04 15:36:07 +0200
committertoni <matzeton@googlemail.com>2016-07-04 15:36:07 +0200
commitcb6047b694a86f78723a613819677227f14e30c3 (patch)
tree4eb9c2f2339c5185fec81447bd832d4d4f0bd3d0
parent7248ec097b19828e047e83df89aa7bac4150c2cd (diff)
parentbc30ed7f5624f7d5ccc1e9937ed7bcb7faae9892 (diff)
Merge branch 'master' into jessie
Conflicts: main.c
-rw-r--r--.gitignore3
-rw-r--r--Makefile37
-rw-r--r--Makefile.am18
-rw-r--r--Makefile.debug58
-rwxr-xr-xautogen.sh15
-rwxr-xr-xcompile.sh11
-rw-r--r--configure.ac83
-rw-r--r--debian/control2
-rwxr-xr-x[-rw-r--r--]debian/naskpass.postinst (renamed from debian/postinst)12
-rwxr-xr-x[-rw-r--r--]debian/naskpass.prerm (renamed from debian/prerm)0
-rwxr-xr-xdebian/rules62
-rwxr-xr-xluks_test.sh27
-rw-r--r--m4/ax_check_typedef.m476
-rw-r--r--main.c159
-rwxr-xr-x[-rw-r--r--]scripts/naskconf8
-rwxr-xr-x[-rw-r--r--]scripts/naskpass.inithook1
-rwxr-xr-x[-rw-r--r--]scripts/naskpass.initscript18
-rw-r--r--src/Makefile.am8
-rw-r--r--src/aconfig.h.in305
-rw-r--r--src/check/check.c65
-rw-r--r--src/config.h (renamed from config.h)15
-rw-r--r--src/log.c51
-rw-r--r--src/log.h16
-rw-r--r--src/main.c200
-rw-r--r--src/opt.c54
-rw-r--r--src/opt.h35
-rw-r--r--src/status.c (renamed from status.c)0
-rw-r--r--src/status.h (renamed from status.h)0
-rw-r--r--src/ui.c325
-rw-r--r--src/ui.h90
-rw-r--r--src/ui_ani.c105
-rw-r--r--src/ui_ani.h43
-rw-r--r--src/ui_elements.c180
-rw-r--r--src/ui_elements.h13
-rw-r--r--src/ui_input.c (renamed from ui_input.c)62
-rw-r--r--src/ui_input.h (renamed from ui_input.h)13
-rw-r--r--src/ui_ipc.c142
-rw-r--r--src/ui_ipc.h57
-rw-r--r--src/ui_statusbar.c (renamed from ui_statusbar.c)13
-rw-r--r--src/ui_statusbar.h (renamed from ui_statusbar.h)4
-rw-r--r--src/ui_txtwindow.c187
-rw-r--r--src/ui_txtwindow.h55
-rw-r--r--tests/Makefile32
-rw-r--r--tests/ipctest.c45
-rw-r--r--tests/mqtest.c64
-rw-r--r--tests/ncurses.c25
-rw-r--r--tests/producer.c38
-rw-r--r--tests/producer_consumer.c39
-rw-r--r--tests/pthread.c50
-rw-r--r--tests/semconfig.h9
-rw-r--r--tests/semtest.c50
-rw-r--r--tests/strsep.c49
-rw-r--r--ui.c337
-rw-r--r--ui.h63
-rw-r--r--ui_ani.c73
-rw-r--r--ui_ani.h27
-rw-r--r--ui_nwindow.c70
-rw-r--r--ui_nwindow.h44
58 files changed, 2777 insertions, 866 deletions
diff --git a/.gitignore b/.gitignore
index b4c01e9..ab9c734 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-/naskpass
*.swp
+*.o
+*.d
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 43d155d..0000000
--- a/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-CFLAGS ?= $(shell ncurses5-config --cflags) -Wall -D_GNU_SOURCE=1
-DBGFLAGS = -g
-LDFLAGS ?= $(shell ncurses5-config --libs) -pthread
-CC := gcc
-INSTALL ?= install
-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 main.c
-
-all: $(BIN)
-
-$(BIN): $(SOURCES)
- $(CC) $(SOURCES) -D_VERSION=\"$(VERSION)\" $(CFLAGS) $(LDFLAGS) -o $(BIN)
-
-debug:
- $(MAKE) CFLAGS='$(CFLAGS) $(DBGFLAGS)'
-
-install:
- $(INSTALL) -D -m 0755 $(BIN) $(DESTDIR)/lib/cryptsetup/naskpass
- $(INSTALL) -D -m 0755 scripts/naskpass.inithook $(DESTDIR)/usr/share/naskpass/naskpass.hook.initramfs
- $(INSTALL) -D -m 0755 scripts/naskpass.initscript $(DESTDIR)/usr/share/naskpass/naskpass.script.initramfs
- $(INSTALL) -D -m 0755 scripts/naskconf $(DESTDIR)/usr/share/naskpass/naskconf
-
-uninstall:
- rm -f $(DESTDIR)/lib/cryptsetup/naskpass
- rm -f $(DESTDIR)/usr/share/initramfs-tools/hooks/naskpass
- rm -f $(DESTDIR)/usr/share/naskpass/naskpass.script.initramfs
- rm -f $(DESTDIR)/usr/share/naskpass/naskconf
- rmdir --ignore-fail-on-non-empty $(DESTDIR)/usr/share/naskpass
-
-clean:
- rm -f $(BIN)
-
-source:
- -dh_make --createorig -p naskpass_$(VERSION) -s -y
-
-.PHONY: all install clean
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..26ab017
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = src
+
+install-exec-local:
+ /bin/mkdir -p '$(prefix)/lib/cryptsetup'
+ /usr/bin/install -c src/naskpass '$(prefix)/lib/cryptsetup/naskpass'
+ /usr/bin/install -c src/naskpass_check '$(prefix)/lib/cryptsetup/naskpass_check'
+ rm '$(prefix)/bin/naskpass'
+ rm '$(prefix)/bin/naskpass_check'
+ rmdir '$(prefix)/bin'
+
+clean-local:
+ rm -f naskpass naskpass_check
+
+distclean-local: clean-local
+ rm -f aclocal.m4 config.log config.status configure
+ rm -f Makefile.in src/Makefile.in src/aconfig.h.in~ src/*.d
+ rm -rf build autom4te.cache
+
diff --git a/Makefile.debug b/Makefile.debug
new file mode 100644
index 0000000..e727221
--- /dev/null
+++ b/Makefile.debug
@@ -0,0 +1,58 @@
+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 -g
+LDFLAGS = $(shell ncurses5-config --libs) -pthread -lrt
+CC = gcc
+INSTALL = install
+STRIP = strip
+BIN_NASKP = naskpass
+BIN_CHECK = $(BIN_NASKP)_check
+BINS = $(BIN_NASKP) $(BIN_CHECK)
+SOURCES = $(wildcard src/*.c)
+OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
+DEPS = $(patsubst %.c,%.d,$(SOURCES))
+
+all: $(OBJECTS) $(BINS)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+$(BIN_NASKP): $(SOURCES)
+ $(CC) $(LDFLAGS) $(OBJECTS) -o $(BIN_NASKP)
+ $(MAKE) -C tests CC='$(CC)' CFLAGS='$(CFLAGS)' all
+
+$(BIN_CHECK): src/check/check.c
+ $(CC) $(CFLAGS) $(LDFLAGS) src/check/check.c -o $(BIN_CHECK)
+
+strip: $(OBJECTS) $(BINS)
+ $(STRIP) $(BIN_NASKP)
+ $(STRIP) $(BIN_CHECK)
+
+release: all strip
+
+debug:
+ @$(MAKE) CFLAGS='$(CFLAGS)
+ @$(MAKE) -C tests CFLAGS='$(CFLAGS)
+
+install:
+ $(INSTALL) -D -m 0755 $(BIN_NASKP) $(DESTDIR)/lib/cryptsetup/naskpass
+ $(INSTALL) -D -m 0755 $(BIN_CHECK) $(DESTDIR)/lib/cryptsetup/naskpass_check
+ $(INSTALL) -D -m 0755 scripts/naskpass.inithook $(DESTDIR)/usr/share/naskpass/naskpass.hook.initramfs
+ $(INSTALL) -D -m 0755 scripts/naskpass.initscript $(DESTDIR)/usr/share/naskpass/naskpass.script.initramfs
+ $(INSTALL) -D -m 0755 scripts/naskconf $(DESTDIR)/usr/share/naskpass/naskconf
+
+uninstall:
+ rm -f $(DESTDIR)/lib/cryptsetup/naskpass
+ rm -f $(DESTDIR)/usr/share/initramfs-tools/hooks/naskpass
+ rm -f $(DESTDIR)/usr/share/naskpass/naskpass.script.initramfs
+ rm -f $(DESTDIR)/usr/share/naskpass/naskconf
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)/usr/share/naskpass
+
+clean:
+ rm -f $(DEPS)
+ rm -f $(OBJECTS)
+ rm -f $(BINS)
+ $(MAKE) -C tests clean
+
+test:
+ $(MAKE) -C tests run
+
+.PHONY: all debug release strip install uninstall clean test
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..96fb4e9
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+rm -f config.cache
+mkdir -p build
+
+echo "Looking in current directory for macros."
+aclocal -I .
+echo "Adding missing files."
+automake --add-missing --force-missing
+echo "Autoconf, Autoheader, Automake"
+autoconf
+autoheader
+automake --foreign --add-missing --force-missing --copy
+exit $?
+
diff --git a/compile.sh b/compile.sh
new file mode 100755
index 0000000..5c7b1d6
--- /dev/null
+++ b/compile.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+
+DIR=$(dirname $0)
+PWD=$(pwd)
+
+cd ${DIR}
+./autogen.sh
+./configure $*
+make
+cd ${PWD}
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..cef76e0
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,83 @@
+# -*- Autoconf -*-
+# configure script generation for ncblog
+#
+
+AC_PREREQ([2.67])
+AC_INIT([naskpass], [0], [matzeton@googlemail.com])
+AC_CONFIG_AUX_DIR([build])
+AM_INIT_AUTOMAKE([1.11 subdir-objects foreign no-define -Wall -Werror])
+AM_WITH_DMALLOC
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CONFIG_SRCDIR([src/aconfig.h.in])
+AC_CONFIG_HEADER([src/aconfig.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_USE_SYSTEM_EXTENSIONS
+CFLAGS=""
+LDFLAGS=""
+
+# Checks for programs.
+AM_PROG_AR
+AM_PROG_INSTALL_STRIP
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+AC_C_INLINE
+AC_PREFIX_DEFAULT([/usr])
+AC_CHECK_TOOL([STRIP],[strip])
+
+# Checks for header files.
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIME
+AC_HEADER_STDBOOL
+AC_HEADER_STDC
+AC_HEADER_STAT
+AC_HEADER_DIRENT
+AC_HEADER_ASSERT
+AC_CHECK_HEADERS([stdio.h stdlib.h stdbool.h string.h unistd.h errno.h sys/stat.h sys/types.h sys/wait.h fcntl.h semaphore.h time.h mqueue.h syslog.h],[],[AC_MSG_ERROR([*** missing essential header files])])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_COMPUTE_INT
+AC_TYPE_UID_T
+AC_TYPE_MODE_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT8_T
+AX_CHECK_TYPEDEF([size_t], [stdio.h],,[AC_MSG_ERROR([*** Missing size_t typedef in stdio.h])])
+AX_CHECK_TYPEDEF([ssize_t], [stdio.h],,[AC_MSG_ERROR([*** Missing size_t typedef in stdio.h])])
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_FUNC_REALLOC
+AC_FUNC_STRNLEN
+AC_FUNC_STAT
+AC_FUNC_MKTIME
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([clock_gettime asprintf system printf fprintf mkfifo stat open close fork memmove memcpy memset strdup strndup strerror strstr strlen strnlen strtol openlog vsyslog closelog],,[AC_MSG_ERROR([*** Missing essential functions.])])
+
+AC_ARG_ENABLE(debug,
+AS_HELP_STRING([--enable-debug],
+ [enable debugging, default: no]),
+[case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+esac],
+[debug=false])
+AM_CONDITIONAL(DEBUG, test x"$debug" = x"true")
+
+AC_DEFINE([HAVE_CONFIG], [1], [Do NOT change THIS!])
+LDFLAGS="${LDFLAGS} -pthread -lrt -lncurses"
+AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_LDFLAGS])
+AC_CONFIG_FILES([Makefile src/Makefile])
+AC_OUTPUT
+
+echo "Run 'make' to finish the process."
+test -d .git && VERSION="git-$(git rev-parse --short HEAD)"
+echo "#define VERSION \"${VERSION}\"" >src/version.h
+
diff --git a/debian/control b/debian/control
index ee161d9..dc3c228 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: naskpass
Section: admin
Priority: extra
Maintainer: Toni Uhlig <matzeton@googlemail.com>
-Build-Depends: debhelper (>= 8.0.0), libncurses5-dev, libtinfo-dev
+Build-Depends: debhelper (>= 8.0.0), libncurses5-dev, libtinfo-dev, autoconf, automake
Standards-Version: 3.9.3
Homepage: https://github.com/freecoding/naskpass.git
#Vcs-Git: git://git.debian.org/collab-maint/naskpass.git
diff --git a/debian/postinst b/debian/naskpass.postinst
index 4306174..4d9cc42 100644..100755
--- a/debian/postinst
+++ b/debian/naskpass.postinst
@@ -9,15 +9,14 @@ set -e
. /usr/share/naskpass/naskconf
case "$1" in
- install)
- ;;
- configure|upgrade)
+ configure)
+ nask_update
db_input high naskpass/activate || true
db_go
db_get naskpass/activate
- if [ "$RET" = "true" ]; then
- nask_activate || true
+ if [ "x$RET" = "xtrue" ]; then
+ nask_activate
if [ "x${ERRMSG}" != "x" ]; then
echo "* ${ERRMSG}" >&2
nask_deactivate
@@ -28,8 +27,7 @@ case "$1" in
update-initramfs -u
;;
- abort-upgrade)
- db_purge
+ install|upgrade|abort-upgrade)
;;
*)
diff --git a/debian/prerm b/debian/naskpass.prerm
index 5b1c46d..5b1c46d 100644..100755
--- a/debian/prerm
+++ b/debian/naskpass.prerm
diff --git a/debian/rules b/debian/rules
index 532ed81..1c41e7c 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,11 +4,61 @@
#export DH_VERBOSE=1
DEBVERS := $(shell dpkg-parsechangelog | sed -n -e 's/^Version: //p')
-%:
- dh $@
-override_dh_auto_build:
- $(MAKE) VERSION="$(DEBVERS)" all
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ ./autogen.sh
+ ./configure
+ echo "#define VERSION \"$(DEBVERS)\"" >src/version.h
+ touch configure-stamp
+
+build: configure-stamp build-stamp
+build-stamp:
+ dh_testdir
+ $(MAKE)
+ $(MAKE) -C tests -f Makefile run
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+ dh_clean
+
+distclean: build
+ $(MAKE) distclean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean
+ dh_prep
+ dh_installdirs
+ dh_installchangelogs
+ dh_installdebconf
+ $(MAKE) install prefix=$(CURDIR)/debian/naskpass
+ mkdir -p $(CURDIR)/debian/naskpass/usr/share/naskpass
+ install -D -m755 ./scripts/naskconf $(CURDIR)/debian/naskpass/usr/share/naskpass/
+ install -D -m755 ./scripts/naskpass.inithook $(CURDIR)/debian/naskpass/usr/share/naskpass/
+ install -D -m755 ./scripts/naskpass.initscript $(CURDIR)/debian/naskpass/usr/share/naskpass/
+
+binary-indep: build install
+
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean distclean binary-indep binary-arch binary install configure
-override_dh_auto_install:
- $(MAKE) DESTDIR=$(CURDIR)/debian/naskpass install
diff --git a/luks_test.sh b/luks_test.sh
new file mode 100755
index 0000000..ebe622c
--- /dev/null
+++ b/luks_test.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -e
+
+
+if [ "x$1" = "x" ] || [ "x$2" = "x" ]; then
+ echo "$0: [FILE] [NAME]"
+ exit 1
+fi
+FILE=$1
+NAME=$2
+
+if [ ! -w ${FILE} ]; then
+ dd if=/dev/zero of=${FILE} bs=1M count=10
+ /sbin/cryptsetup luksFormat ${FILE}
+fi
+
+sudo src/naskpass -l -f ./testfifo -c "/sbin/cryptsetup open ${FILE} ${NAME}"
+
+set +e
+sudo /sbin/cryptsetup status ${NAME}
+ret=$?
+set -e
+
+if [ $ret -eq 0 ]; then
+ sudo /sbin/cryptsetup close ${NAME}
+ /bin/echo -e "\n$0: close'd"
+fi
diff --git a/m4/ax_check_typedef.m4 b/m4/ax_check_typedef.m4
new file mode 100644
index 0000000..13b9d5e
--- /dev/null
+++ b/m4/ax_check_typedef.m4
@@ -0,0 +1,76 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_typedef.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_TYPEDEF(TYPEDEF, HEADER [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]])
+#
+# DESCRIPTION
+#
+# Check if the given typedef-name is recognized as a type. The trick is to
+# use a sizeof(TYPEDEF) and see if the compiler is happy with that.
+#
+# This can be thought of as a mixture of AC_CHECK_TYPE(TYPEDEF,DEFAULT)
+# and AC_CHECK_LIB(LIBRARY,FUNCTION,ACTION-IF-FOUND,ACTION-IF-NOT-FOUND).
+#
+# A convenience macro AX_CHECK_TYPEDEF_ is provided that will not emit any
+# message to the user - it just executes one of the actions.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AU_ALIAS([AC_CHECK_TYPEDEF], [AX_CHECK_TYPEDEF])
+AC_DEFUN([AX_CHECK_TYPEDEF_],
+[dnl
+ac_lib_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_CACHE_VAL(ac_cv_lib_$ac_lib_var,
+[ eval "ac_cv_type_$ac_lib_var='not-found'"
+ ac_cv_check_typedef_header=`echo ifelse([$2], , stddef.h, $2)`
+ AC_TRY_COMPILE( [#include <$ac_cv_check_typedef_header>],
+ [int x = sizeof($1); x = x;],
+ eval "ac_cv_type_$ac_lib_var=yes" ,
+ eval "ac_cv_type_$ac_lib_var=no" )
+ if test `eval echo '$ac_cv_type_'$ac_lib_var` = "no" ; then
+ ifelse([$4], , :, $4)
+ else
+ ifelse([$3], , :, $3)
+ fi
+])])
+
+dnl AX_CHECK_TYPEDEF(TYPEDEF, HEADER [, ACTION-IF-FOUND,
+dnl [, ACTION-IF-NOT-FOUND ]])
+AC_DEFUN([AX_CHECK_TYPEDEF],
+[dnl
+ AC_MSG_CHECKING([for $1 in $2])
+ AX_CHECK_TYPEDEF_($1,$2,AC_MSG_RESULT(yes),AC_MSG_RESULT(no))dnl
+])
diff --git a/main.c b/main.c
deleted file mode 100644
index 416b20f..0000000
--- a/main.c
+++ /dev/null
@@ -1,159 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-
-#include "ui_ani.h"
-#include "ui_input.h"
-#include "ui_statusbar.h"
-#include "ui.h"
-#include "config.h"
-
-
-static bool ui_active = true;
-
-static void
-usage(char *arg0)
-{
- fprintf(stderr, "%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 <http://gnu.org/licenses/gpl.html>.\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, "stat: %s is not a FIFO\n", fifo_path);
- return (false);
- }
- }
- }
- }
- perror("check_fifo");
- 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)
-{
- int retval;
- char *cmd;
-
- if (crypt_cmd == NULL || pass == NULL) return (-1);
- asprintf(&cmd, "echo '%s' | %s", pass, crypt_cmd);
- retval = system(cmd);
- return (retval);
-}
-
-int
-main(int argc, char **argv)
-{
- int ffd, opt;
- pid_t child;
- char pbuf[MAX_PASSWD_LEN+1];
- char *fifo_path = NULL;
- char *crypt_cmd = NULL;
-
- 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);
- case 'f':
- fifo_path = strdup(optarg);
- break;
- case 'c':
- crypt_cmd = strdup(optarg);
- break;
- default:
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- }
- if (optind < argc) {
- fprintf(stderr, "%s: I dont understand you.\n\n", argv[0]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- if (fifo_path == NULL) fifo_path = strdup(DEFAULT_FIFO);
-
- if (check_fifo(fifo_path) == false) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- if ((ffd = open(fifo_path, O_NONBLOCK | O_RDWR)) < 0) {
- fprintf(stderr, "fifo: %s\n", fifo_path);
- perror("open");
- exit(EXIT_FAILURE);
- }
-
- if ((child = fork()) == 0) {
- /* child */
- ui_active = true;
- do_ui(ffd);
- ui_active = false;
- } else if (child > 0) {
- /* parent */
- fclose(stdin);
- while (input_timeout(ffd, 1) == 0) {
- usleep(100000);
- if (ui_active == true) {
- // TODO: smthng
- }
- }
- stop_ui();
- wait(&child);
- 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);
- }
-
- close(ffd);
- if (crypt_cmd != NULL) free(crypt_cmd);
- free(fifo_path);
- return (EXIT_SUCCESS);
-}
diff --git a/scripts/naskconf b/scripts/naskconf
index 4a4a7e0..5f82f22 100644..100755
--- a/scripts/naskconf
+++ b/scripts/naskconf
@@ -14,8 +14,8 @@ _nask_cmd () {
return 1
fi
dpkg-divert --package naskpass --add --rename --divert /var/backups/cryptroot.initramfs.bak ${ORGFILE}
- cp /usr/share/naskpass/naskpass.script.initramfs ${ORGFILE}
- ln -s /usr/share/naskpass/naskpass.hook.initramfs \
+ cp /usr/share/naskpass/naskpass.initscript ${ORGFILE}
+ ln -s /usr/share/naskpass/naskpass.inithook \
/usr/share/initramfs-tools/hooks/naskpass
db_set naskpass/active true
elif [ "x$1" = "xDCTV" ] && [ "$RET" = "true" ]; then
@@ -23,9 +23,13 @@ _nask_cmd () {
rm /usr/share/initramfs-tools/hooks/naskpass
dpkg-divert --package naskpass --rename --remove ${ORGFILE}
db_set naskpass/active false
+ elif [ "x$1" = "xUPDT" ] && [ "$RET" = "true" ]; then
+ cp /usr/share/naskpass/naskpass.initscript ${ORGFILE}
fi
return 0
}
nask_activate () { _nask_cmd "ACTV"; return $?; }
nask_deactivate () { _nask_cmd "DCTV"; return $?; }
+nask_update () { _nask_cmd "UPDT"; return $?; }
+
diff --git a/scripts/naskpass.inithook b/scripts/naskpass.inithook
index 083c477..074dff3 100644..100755
--- a/scripts/naskpass.inithook
+++ b/scripts/naskpass.inithook
@@ -19,6 +19,7 @@ esac
. /usr/share/initramfs-tools/hook-functions
copy_exec /lib/cryptsetup/naskpass /lib/cryptsetup
+copy_exec /lib/cryptsetup/naskpass_check /lib/cryptsetup
mkdir -p ${DESTDIR}/lib/terminfo/l
cp /lib/terminfo/l/linux ${DESTDIR}/lib/terminfo/l/
diff --git a/scripts/naskpass.initscript b/scripts/naskpass.initscript
index a2d7e95..98fd1dc 100644..100755
--- a/scripts/naskpass.initscript
+++ b/scripts/naskpass.initscript
@@ -290,7 +290,7 @@ setup_mapping()
# Plymouth will add a : if it is a non-graphical prompt
cryptkey="Please unlock disk $diskname"
else
- if [ -x /lib/cryptsetup/naskpass ]; then
+ if [ -x /lib/cryptsetup/naskpass ] && [ $askpass_fallback -eq 0 ]; then
cryptkeyscript="/lib/cryptsetup/naskpass"
cryptkey=""
else
@@ -302,22 +302,24 @@ setup_mapping()
if [ ! -e "$NEWROOT" ]; then
- if [ -x /bin/plymouth ] && plymouth --ping; then
- message "naskpass does not work with playmouth, falling back to default askpass .."
+ if [ -x /bin/plymouth ] && plymouth --ping || [ $askpass_fallback -ne 0 ]; then
+ if [ $askpass_fallback -eq 0 ]; then
+ message "naskpass does not work with plymouth, falling back to default askpass .."
+ fi
if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \
$cryptkeyscript "$cryptkey" | $cryptopen; then
message "cryptsetup: cryptsetup failed, bad password or options?"
continue
fi
else
- dmesg -D
- if ! $cryptkeyscript -c "cryptsetup -T 1 open $cryptsource $crypttarget"; then
+ dmesg -n 1
+ if ! $cryptkeyscript -c "/sbin/cryptsetup -T 1 open $cryptsource $crypttarget"; then
message "naskpass: failed"
continue
else
message "naskpass: success"
fi
- dmesg -E
+ dmesg -n 4
fi
fi
@@ -383,6 +385,7 @@ setup_mapping()
#
# Do we have any kernel boot arguments?
+askpass_fallback=0
cmdline_cryptopts=''
unset cmdline_root
for opt in $(cat /proc/cmdline); do
@@ -406,6 +409,9 @@ for opt in $(cat /proc/cmdline); do
*) # lilo major/minor number (See #398957). Ignore
esac
;;
+ cryptfallback)
+ askpass_fallback=1
+ ;;
esac
done
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..44d2220
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,8 @@
+bin_PROGRAMS=naskpass naskpass_check
+naskpass_SOURCES=main.c log.c opt.c status.c ui_ani.c ui.c ui_elements.c ui_input.c ui_ipc.c ui_txtwindow.c ui_statusbar.c
+naskpass_check_SOURCES=check/check.c
+if DEBUG
+naskpass_CFLAGS=-O0 -g3 -DDEBUG
+else
+naskpass_CFLAGS=-Os
+endif
diff --git a/src/aconfig.h.in b/src/aconfig.h.in
new file mode 100644
index 0000000..8dcbf12
--- /dev/null
+++ b/src/aconfig.h.in
@@ -0,0 +1,305 @@
+/* src/aconfig.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the `close' function. */
+#undef HAVE_CLOSE
+
+/* Define to 1 if you have the `closelog' function. */
+#undef HAVE_CLOSELOG
+
+/* Do NOT change THIS! */
+#undef HAVE_CONFIG
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `fprintf' function. */
+#undef HAVE_FPRINTF
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkfifo' function. */
+#undef HAVE_MKFIFO
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the <mqueue.h> header file. */
+#undef HAVE_MQUEUE_H
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the `open' function. */
+#undef HAVE_OPEN
+
+/* Define to 1 if you have the `openlog' function. */
+#undef HAVE_OPENLOG
+
+/* Define to 1 if you have the `printf' function. */
+#undef HAVE_PRINTF
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the <semaphore.h> header file. */
+#undef HAVE_SEMAPHORE_H
+
+/* Define to 1 if you have the `stat' function. */
+#undef HAVE_STAT
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlen' function. */
+#undef HAVE_STRLEN
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the `system' function. */
+#undef HAVE_SYSTEM
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define to 1 if assertions should be disabled. */
+#undef NDEBUG
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Define if using the dmalloc debugging malloc package */
+#undef WITH_DMALLOC
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/src/check/check.c b/src/check/check.c
new file mode 100644
index 0000000..9d28129
--- /dev/null
+++ b/src/check/check.c
@@ -0,0 +1,65 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <semaphore.h>
+#include <mqueue.h>
+
+
+#define myassert(x, emask) if ((x)) { ret &= ret; } else { ret |= emask; }
+
+static volatile unsigned long long int ret = 0x0;
+static mqd_t mq_test;
+static mqd_t mq_recv;
+static sem_t *sp_test;
+static const size_t bufsiz = 256;
+
+int main(int argc, char **argv)
+{
+ int c_stat;
+ struct mq_attr m_attr;
+ char buf[bufsiz], recv[bufsiz];
+ unsigned int prio;
+ ssize_t sz_recv;
+
+ memset(buf, '\0', bufsiz);
+ memset(recv, '\0', bufsiz);
+ if (argc > 1)
+ strncpy(buf, argv[1], bufsiz-1);
+
+ m_attr.mq_flags = 0;
+ m_attr.mq_msgsize = bufsiz;
+ m_attr.mq_maxmsg = 10;
+ m_attr.mq_curmsgs = 0;
+
+ mq_unlink("/testmq");
+ myassert( (mq_test = mq_open( "/testmq", O_NONBLOCK | O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG, &m_attr )) != (mqd_t)-1, 0x1 );
+ myassert( mq_getattr(mq_test, &m_attr) == 0, 0x2 );
+
+ strcpy(buf, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ");
+ myassert( mq_send(mq_test, buf, bufsiz, 0) == 0, 0x4 );
+ myassert( (sz_recv = mq_receive(mq_test, recv, bufsiz, &prio)) > 0, 0x8 );
+
+ memset(recv, '\0', bufsiz);
+ if (fork() > 0) {
+ myassert( (mq_recv = mq_open( "/testmq", O_RDONLY, S_IRWXU | S_IRWXG, &m_attr )) != (mqd_t)-1, 0x10 );
+ myassert( (sz_recv = mq_receive(mq_recv, recv, bufsiz, &prio)) > 0, 0x20 );
+ return ret;
+ }
+ myassert( mq_send(mq_test, buf, bufsiz, 0) == 0, 0x40 );
+ wait(&c_stat);
+ myassert( c_stat == 0xFF, 0x80 );
+ myassert( mq_close(mq_test) == 0, 0x100 );
+ myassert( mq_unlink("/testmq") == 0, 0x200 );
+
+ myassert( sem_unlink("/testsem") == 0, 0x400 );
+ myassert( (sp_test = sem_open("/testsem", O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)), 0x800 );
+ myassert( sem_post(sp_test) == 0, 0x1000 );
+ myassert( sem_wait(sp_test) == 0, 0x1200 );
+ myassert( sem_close(sp_test) == 0, 0x1400 );
+ myassert( sem_unlink("/testsem") == 0, 0x1800 );
+
+ return ret;
+}
diff --git a/config.h b/src/config.h
index 26fdb3c..797376f 100644
--- a/config.h
+++ b/src/config.h
@@ -5,8 +5,17 @@
#define DEFAULT_FIFO "/lib/cryptsetup/passfifo"
#define SHTDWN_CMD "echo 'o' >/proc/sysrq-trigger"
-#ifdef _VERSION
-#define VERSION _VERSION
-#else
+#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"
+
+#ifdef HAVE_CONFIG_H
+#include "version.h"
+#endif
+
+#ifndef VERSION
#define VERSION "unknown"
#endif
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..cd8fc7c
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+#include "log.h"
+
+#define LOG_BUFSIZ 128
+
+static FILE* logfile = NULL;
+
+
+int log_init(char* file)
+{
+ if (!file) {
+ openlog("naskpass", LOG_NDELAY | LOG_PID, LOG_DAEMON);
+ return 0;
+ } else {
+ logfile = fopen(file, "a+");
+ return (logfile ? 0 : errno);
+ }
+}
+
+void log_free(void)
+{
+ if (!logfile) {
+ closelog();
+ } else {
+ fclose(logfile);
+ logfile = NULL;
+ }
+}
+
+int logs(char* format, ...)
+{
+ int ret;
+ va_list vargs;
+
+ va_start(vargs, format);
+ if (!logfile) {
+ vsyslog(LOG_DEBUG, format, vargs);
+ ret = 0;
+ } else {
+ ret = vfprintf(logfile, format, vargs);
+ fflush(logfile);
+ }
+ va_end(vargs);
+ return ret;
+}
+
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..113141b
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,16 @@
+#ifndef LOG_H
+#define LOG_H 1
+
+#ifdef DEBUG
+#define logs_dbg(fmt, ...) logs(fmt, __VA_ARGS__)
+#else
+#define logs_dbg(fmt, ...)
+#endif
+
+int log_init(char* file);
+
+void log_free(void);
+
+int logs(char* format, ...);
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..523422f
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <time.h>
+#include <mqueue.h>
+
+#include "config.h"
+#include "opt.h"
+#include "log.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 >/devnull 2>/dev/null", 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);
+ if ( parse_cmd(argc, argv) != 0 )
+ goto error;
+ log_init( GETOPT(LOG_FILE).str );
+ logs("%s\n", "log init");
+ logs_dbg("%s\n", "debug mode active");
+ if (OPT(CRYPT_CMD).found == 0) {
+ fprintf(stderr, "%s: crypt cmd is mandatory\n", argv[0]);
+ goto error;
+ }
+ if (check_fifo(GETOPT(FIFO_PATH).str) == false) {
+ 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 */
+ logs("%s\n", "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 */
+ logs("%s\n", "parent");
+ fclose(stdin);
+ fclose(stdout);
+ /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */
+ ui_ipc_sempost(SEM_BS);
+ while ( ui_ipc_getvalue(SEM_UI) > 0 ) {
+ logs_dbg("loop start (SEM_BS=%d, SEM_IN=%d, SEM_UI=%d).\n", ui_ipc_getvalue(SEM_BS), ui_ipc_getvalue(SEM_IN), ui_ipc_getvalue(SEM_UI));
+ ui_ipc_sempost(SEM_BS);
+ if (read(ffd, pbuf, IPC_MQSIZ) >= 0) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY_FD));
+ if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR));
+ }
+ } else if ( ui_ipc_msgcount(MQ_PW) > 0 ) {
+ ui_ipc_msgrecv(MQ_PW, pbuf);
+ logs_dbg("%s\n", "password");
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY));
+ if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) {
+ logs_dbg("%s\n", "cryptcreate error");
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR));
+ } else {
+ logs_dbg("%s\n", "cryptcreate success, trywait SEM_UI");
+ ui_ipc_semtrywait(SEM_UI);
+ }
+ logs_dbg("%s\n", "wait SEM_IN");
+ ui_ipc_semwait(SEM_IN);
+ }
+ logs_dbg("%s (SEM_BS=%d)\n", "wait SEM_BS", ui_ipc_getvalue(SEM_BS));
+ ui_ipc_semwait(SEM_BS);
+ usleep(100000);
+ waitpid(child, &c_status, WNOHANG);
+ if ( WIFEXITED(&c_status) != 0 ) {
+ logs("%s\n", "child exited");
+ break;
+ }
+ logs_dbg("loop end (SEM_BS=%d, SEM_IN=%d, SEM_UI=%d).\n", ui_ipc_getvalue(SEM_BS), ui_ipc_getvalue(SEM_IN), ui_ipc_getvalue(SEM_UI));
+ }
+ logs("%s\n", "waiting for child");
+ wait(&c_status);
+ memset(pbuf, '\0', IPC_MQSIZ+1);
+ } else {
+ /* fork error */
+ perror("fork");
+ goto error;
+ }
+
+ ret = EXIT_SUCCESS;
+error:
+ logs("%s\n", "exiting ..");
+ if (ffd >= 0) close(ffd);
+ ui_ipc_free(1);
+ log_free();
+ exit(ret);
+}
diff --git a/src/opt.c b/src/opt.c
new file mode 100644
index 0000000..0c2071a
--- /dev/null
+++ b/src/opt.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#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), 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 <http://gnu.org/licenses/gpl.html>.\n\n");
+ fprintf(stderr, " Command:\n\t%s [args]\n", arg0);
+ fprintf(stderr, " Arguments:\n\t-h this\n\t-l [logfile]\n\t-f [passfifo] default: %s\n\t-c [cryptcreate]\n", GETOPT(FIFO_PATH).str);
+}
+
+int
+parse_cmd(int argc, char **argv)
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "hf:c:l::")) != -1) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ return 1;
+ case 'f':
+ SETOPT_str(FIFO_PATH, strdup(optarg));
+ break;
+ case 'c':
+ SETOPT_str(CRYPT_CMD, strdup(optarg));
+ break;
+ case 'l':
+ if (optarg) {
+ SETOPT_str(LOG_FILE, strdup(optarg));
+ } else SETOPT_str(LOG_FILE, NULL);
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/opt.h b/src/opt.h
new file mode 100644
index 0000000..57777de
--- /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 SETOPT_str(opt_index, value) { OPT(opt_index).found = 1; OPT(opt_index).opt.str = value; }
+#define GETOPT(opt_index) (OPT(opt_index).found != 0 ? OPT(opt_index).opt : OPT(opt_index).def)
+
+
+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,
+ LOG_FILE
+};
+
+
+extern struct opt config_opts[];
+
+void
+usage(char *arg0);
+
+int
+parse_cmd(int argc, char **argv);
+
+#endif
diff --git a/status.c b/src/status.c
index 5286ddf..5286ddf 100644
--- a/status.c
+++ b/src/status.c
diff --git a/status.h b/src/status.h
index 995d08a..995d08a 100644
--- a/status.h
+++ b/src/status.h
diff --git a/src/ui.c b/src/ui.c
new file mode 100644
index 0000000..360f015
--- /dev/null
+++ b/src/ui.c
@@ -0,0 +1,325 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string.h>
+#include <ncurses.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#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_txtwindow.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 unsigned int cur_x, cur_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;
+ }
+}
+
+unsigned int
+ui_get_maxx(void)
+{
+ return max_x;
+}
+
+unsigned int
+ui_get_maxy(void)
+{
+ return max_y;
+}
+
+void
+ui_set_cur(unsigned int x, unsigned int y)
+{
+ cur_x = x;
+ cur_y = y;
+}
+
+unsigned int
+ui_get_curx(void)
+{
+ return (cur_x);
+}
+
+unsigned int
+ui_get_cury(void)
+{
+ return (cur_y);
+}
+
+int
+activate_ui_input(void *data)
+{
+ int ret = DOUI_ERR;
+ 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;
+ ret = DOUI_OK;
+ break;
+ }
+ }
+ cur = cur->next;
+ }
+ return ret;
+}
+
+int
+deactivate_ui_input(void *data)
+{
+ int ret = DOUI_ERR;
+
+ if (active != NULL && data == active->data) {
+ active = NULL;
+ ret = DOUI_OK;
+ }
+ return ret;
+}
+
+static bool
+process_key(char key)
+{
+ bool ret = false;
+
+ if ( active != NULL ) {
+ ret = ( active->cbs.ui_input(active->wnd, active->data, key) == DOUI_OK ? true : false );
+ }
+ return ret;
+}
+
+static int
+do_ui_update(bool timed_out)
+{
+ int retval = UICB_OK;
+ struct nask_ui *cur = nui;
+
+ /* call all draw callback's */
+ erase();
+ if (timed_out == TRUE && atmout > 0) {
+ atmout--;
+ } else if (timed_out == TRUE && atmout == 0) {
+ ui_ipc_semwait(SEM_UI);
+ } else {
+ atmout = APP_TIMEOUT;
+ }
+ 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, cur_y, cur_x);
+ wrefresh(wnd_main);
+ return (retval);
+}
+
+static void *
+ui_thrd(void *arg)
+{
+ int cnd_ret;
+ struct timespec now;
+
+ do_ui_update(true);
+ ui_ipc_sempost(SEM_RD);
+ pthread_mutex_lock(&mtx_update);
+ clock_gettime(CLOCK_REALTIME, &now);
+ now.tv_sec += UILOOP_TIMEOUT;
+ while ( ui_ipc_getvalue(SEM_UI) > 0 ) {
+ cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &now);
+ pthread_mutex_lock(&mtx_busy);
+ do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) );
+ pthread_mutex_unlock(&mtx_busy);
+ if (cnd_ret == ETIMEDOUT) {
+ clock_gettime(CLOCK_REALTIME, &now);
+ now.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);
+}
+
+void
+ui_thrd_suspend(void)
+{
+ pthread_mutex_lock(&mtx_busy);
+}
+
+void
+ui_thrd_resume(void)
+{
+ pthread_mutex_unlock(&mtx_busy);
+}
+
+WINDOW *
+init_ui(void)
+{
+ wnd_main = initscr();
+ max_x = getmaxx(wnd_main);
+ max_y = getmaxy(wnd_main);
+ cur_x = getcurx(wnd_main);
+ cur_y = getcury(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);
+ /* TXTwindow */
+ init_pair(4, COLOR_YELLOW, COLOR_RED);
+ init_pair(5, COLOR_WHITE, COLOR_CYAN);
+ /* EoF TXTwindow */
+ raw();
+ keypad(stdscr, TRUE);
+ noecho();
+ nodelay(stdscr, TRUE);
+ 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);
+ pthread_mutex_unlock(&mtx_update);
+ wtimeout(stdscr, 500);
+ while ( ui_ipc_getvalue(SEM_UI) > 0 ) {
+ if ((key = wgetch(wnd_main)) == ERR) {
+ continue;
+ }
+ if ( process_key(key) != true ) {
+ raise(SIGTERM);
+ }
+ 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..8aa1d55
--- /dev/null
+++ b/src/ui.h
@@ -0,0 +1,90 @@
+#ifndef UI_H
+#define UI_H 1
+
+#include <ncurses.h>
+#include <stdint.h>
+
+#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);
+
+unsigned int
+ui_get_maxx(void);
+
+unsigned int
+ui_get_maxy(void);
+
+void
+ui_set_cur(unsigned int x, unsigned int y);
+
+unsigned int
+ui_get_curx(void);
+
+unsigned int
+ui_get_cury(void);
+
+int
+activate_ui_input(void *data);
+
+int
+deactivate_ui_input(void *data);
+
+void
+ui_thrd_force_update(void);
+
+void
+ui_thrd_suspend(void);
+
+void
+ui_thrd_resume(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 <stdlib.h>
+#include <string.h>
+
+#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 <ncurses.h>
+
+
+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..f072d45
--- /dev/null
+++ b/src/ui_elements.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ui.h"
+#include "ui_ipc.h"
+#include "ui_ani.h"
+#include "ui_input.h"
+#include "ui_statusbar.h"
+#include "ui_txtwindow.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 1
+#define BSTR_LEN 3
+
+static struct input *pw_input;
+static struct anic *heartbeat;
+static struct statusbar *higher, *lower;
+static struct txtwindow *infownd;
+static struct tctwindow *errwnd;
+static char *title = NULL;
+static char busy_str[BSTR_LEN+1] = ".\0\0\0";
+
+
+static int
+lower_statusbar_update(WINDOW *win, struct statusbar *bar, bool ui_timeout)
+{
+ if (ui_timeout == FALSE) return DOUI_OK;
+ char *tmp = get_system_stat();
+ set_statusbar_text(bar, tmp);
+ free(tmp);
+ return DOUI_OK;
+}
+
+static int
+higher_statusbar_update(WINDOW *win, struct statusbar *bar, bool ui_timeout)
+{
+ return DOUI_OK;
+}
+
+static int
+infownd_update(WINDOW *win, struct txtwindow *tw, bool ui_timeout)
+{
+ if (ui_timeout == TRUE && tw->active == TRUE) {
+ size_t len = strlen(busy_str);
+ if (len > BSTR_LEN) {
+ memset(busy_str, '\0', BSTR_LEN+1);
+ busy_str[0] = '.';
+ } else strcat(busy_str, ".");
+ }
+ return DOUI_OK;
+}
+
+static int
+passwd_input_cb(WINDOW *wnd, void *data, int key)
+{
+ struct input *a = (struct input *) data;
+ char ipc_buf[IPC_MQSIZ+1];
+
+ memset(ipc_buf, '\0', IPC_MQSIZ+1);
+// wtimeout(stdscr, -1);
+ switch (key) {
+ case UIKEY_ENTER:
+ ui_ipc_msgsend(MQ_PW, a->input);
+
+ ui_thrd_suspend();
+ clear_input(wnd, a);
+ deactivate_input(pw_input);
+ ui_thrd_resume();
+
+ ui_ipc_msgrecv(MQ_IF, ipc_buf);
+
+ ui_thrd_suspend();
+ set_txtwindow_color(infownd, COLOR_PAIR(5), COLOR_PAIR(5));
+ set_txtwindow_title(infownd, "BUSY");
+ set_txtwindow_text(infownd, ipc_buf);
+ set_txtwindow_active(infownd, true);
+ ui_thrd_resume();
+ ui_thrd_force_update();
+
+ sleep(2);
+
+ if (ui_ipc_msgcount(MQ_IF) > 0) {
+ ui_ipc_msgrecv(MQ_IF, ipc_buf);
+ ui_thrd_suspend();
+ set_txtwindow_color(infownd, COLOR_PAIR(4), COLOR_PAIR(4) | A_BOLD);
+ set_txtwindow_title(infownd, "ERROR");
+ set_txtwindow_text(infownd, ipc_buf);
+ ui_thrd_resume();
+ while (wgetch(stdscr) != '\n') { };
+ }
+
+ ui_thrd_suspend();
+ set_txtwindow_active(infownd, false);
+ activate_input(pw_input);
+ ui_thrd_resume();
+
+ ui_ipc_sempost(SEM_IN);
+ break;
+ case UIKEY_BACKSPACE:
+ del_input(wnd, a);
+ break;
+ case UIKEY_ESC:
+ wtimeout(stdscr, 0);
+ ui_thrd_suspend();
+ deactivate_input(pw_input);
+ set_txtwindow_active(infownd, true);
+ set_txtwindow_color(infownd, COLOR_PAIR(5), COLOR_PAIR(5));
+ set_txtwindow_title(infownd, "BUSY");
+ set_txtwindow_text(infownd, "bye bye");
+ ui_thrd_resume();
+ ui_thrd_force_update();
+ sleep(2);
+ 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);
+ }
+// wtimeout(stdscr, 1000);
+ refresh();
+ 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_centered(INFOWND_WIDTH, INFOWND_HEIGHT,
+ infownd_update);
+
+ register_input(NULL, pw_input, passwd_input_cb);
+ register_statusbar(higher);
+ register_statusbar(lower);
+ register_anic_default(heartbeat);
+ register_txtwindow(infownd);
+ activate_input(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_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/ui_input.c b/src/ui_input.c
index 63d8bee..9c53330 100644
--- a/ui_input.c
+++ b/src/ui_input.c
@@ -101,31 +101,39 @@ print_input(WINDOW *win, struct input *a)
print_wnd(3, a);
attron(a->attrs);
- if (win == NULL) {
+ 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) = '_';
- }
- mvprintw(a->y, a->x + p_len, tmp);
- free(tmp);
+ }
+ 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)
+activate_input(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 (UICB_OK);
+ curs_set(1);
+ ui_set_cur(a->x + strlen(a->prompt) + a->cur_pos, a->y);
+ return (activate_ui_input( (void *) a ));
+}
+
+int
+deactivate_input(struct input *a)
+{
+ curs_set(0);
+ return (deactivate_ui_input(a));
}
int
@@ -137,7 +145,7 @@ add_input(WINDOW *win, struct input *a, int 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);
+ ui_set_cur(a->x + strlen(a->prompt) + a->cur_pos, a->y);
return (UICB_OK);
}
@@ -158,11 +166,23 @@ del_input(WINDOW *win, struct input *a)
--a->cur_pos;
}
mvwprintw(win, a->y, a->x + a->cur_pos + strlen(a->prompt), "_");
- print_input(win, a);
+ ui_set_cur(a->x + strlen(a->prompt) + a->cur_pos, a->y);
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;
+ ui_set_cur(a->x + strlen(a->prompt) + a->cur_pos, a->y);
+ return (UICB_OK);
+}
+
+static int
input_cb(WINDOW *win, void *data, bool timed_out)
{
struct input *a = (struct input *) data;
@@ -174,7 +194,11 @@ input_cb(WINDOW *win, void *data, bool timed_out)
}
void
-register_input(WINDOW *win, struct input *a)
+register_input(WINDOW *win, struct input *a, uicb_input ipcb)
{
- register_ui_elt(input_cb, (void *) a, win);
+ 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/src/ui_input.h
index e65d560..df7088c 100644
--- a/ui_input.h
+++ b/src/ui_input.h
@@ -16,6 +16,7 @@ struct input {
char *prompt;
chtype attrs;
chtype shadow;
+ uicb_input cb_input;
};
struct input *
@@ -25,7 +26,10 @@ void
free_input(struct input *a);
int
-activate_input(WINDOW *win, struct input *a);
+activate_input(struct input *a);
+
+int
+deactivate_input(struct input *a);
int
add_input(WINDOW *win, struct input *a, int key);
@@ -34,9 +38,12 @@ int
del_input(WINDOW *win, struct input *a);
int
-input_cb(WINDOW *win, void *data, bool timed_out);
+clear_input(WINDOW *win, struct input *a);
+
+void
+register_input(WINDOW *win, struct input *a, uicb_input ipcb);
void
-register_input(WINDOW *win, struct input *a);
+unregister_input(struct input *a);
#endif
diff --git a/src/ui_ipc.c b/src/ui_ipc.c
new file mode 100644
index 0000000..cf137e7
--- /dev/null
+++ b/src/ui_ipc.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef SEM_TIMEDWAIT
+#include <time.h>
+#endif
+#include <semaphore.h>
+#include <mqueue.h>
+#include <sys/stat.h>
+#include <alloca.h>
+#include <errno.h>
+
+#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)
+{
+ char *tmp = alloca(IPC_MQSIZ);
+ memset(tmp, '\0', IPC_MQSIZ);
+ strncpy(tmp, msg_ptr, IPC_MQSIZ);
+ return ( mq_send(msqs[e_mq], tmp, IPC_MQSIZ, 0) );
+}
+
+ssize_t
+ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr)
+{
+ return mq_receive(msqs[e_mq], msg_ptr, IPC_MQSIZ, NULL);
+}
+
+long
+ui_ipc_msgcount(enum UI_IPC_MSQ e_mq)
+{
+ struct mq_attr m_attr;
+ bzero(&m_attr, sizeof(struct mq_attr));
+ if (mq_getattr(msqs[e_mq], &m_attr) != 0) return -1;
+ return m_attr.mq_curmsgs;
+}
diff --git a/src/ui_ipc.h b/src/ui_ipc.h
new file mode 100644
index 0000000..5ecfaa4
--- /dev/null
+++ b/src/ui_ipc.h
@@ -0,0 +1,57 @@
+#ifndef UI_IPC_H
+#define UI_IPC_H 1
+
+#include "status.h"
+#include "config.h"
+
+#define IPC_MQSIZ 128
+
+
+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);
+
+ssize_t
+ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr);
+
+long
+ui_ipc_msgcount(enum UI_IPC_MSQ e_mq);
+
+#endif
diff --git a/ui_statusbar.c b/src/ui_statusbar.c
index 8172433..df88683 100644
--- a/ui_statusbar.c
+++ b/src/ui_statusbar.c
@@ -36,11 +36,6 @@ statusbar_cb(WINDOW *win, void *data, bool timed_out)
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) {
@@ -50,6 +45,9 @@ statusbar_cb(WINDOW *win, void *data, bool timed_out)
memset(tmp, ' ', a->width);
tmp[a->width] = '\0';
strncpy((tmp + diff_pos), a->text, len);
+ if (a->status_func != NULL) {
+ a->status_func(win, a, timed_out);
+ }
if (win != NULL) {
mvwprintw(win, a->y, 0, tmp);
} else {
@@ -63,7 +61,10 @@ statusbar_cb(WINDOW *win, void *data, bool timed_out)
void
register_statusbar(struct statusbar *a)
{
- register_ui_elt(statusbar_cb, (void *) a, NULL);
+ struct ui_callbacks cbs;
+ cbs.ui_element = statusbar_cb;
+ cbs.ui_input = NULL;
+ register_ui_elt(&cbs, (void *) a, NULL);
}
inline void
diff --git a/ui_statusbar.h b/src/ui_statusbar.h
index 5139c14..65e9e12 100644
--- a/ui_statusbar.h
+++ b/src/ui_statusbar.h
@@ -8,11 +8,11 @@ struct statusbar {
unsigned int y;
unsigned int width;
char *text;
- int (*status_func)(WINDOW *, struct statusbar *);
+ int (*status_func)(WINDOW *, struct statusbar *, bool);
chtype attrs;
};
-typedef int (*status_func)(WINDOW *, struct statusbar *);
+typedef int (*status_func)(WINDOW *, struct statusbar *, bool);
struct statusbar *
init_statusbar(unsigned int y, unsigned int width, chtype attrs, status_func cb_update);
diff --git a/src/ui_txtwindow.c b/src/ui_txtwindow.c
new file mode 100644
index 0000000..90d152d
--- /dev/null
+++ b/src/ui_txtwindow.c
@@ -0,0 +1,187 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "ui_txtwindow.h"
+
+
+struct txtwindow *
+init_txtwindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height, 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 = 0;
+ a->text_attrs = 0;
+ a->window_func = cb_update;
+ return (a);
+}
+
+struct txtwindow *
+init_txtwindow_centered(unsigned int width, unsigned int height, window_func cb_update)
+{
+ unsigned int x = (ui_get_maxx()/2)-(width/2);
+ unsigned int y = (ui_get_maxy()/2)-(height/2);
+ return init_txtwindow(x, y, width, height, cb_update);
+}
+
+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+1; i++)
+ mvprintw(i, x, tmp);
+ /* print window border */
+ mvhline(y-2, x, 0, w);
+ mvhline(y+h+1, 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+1+h, x-1, ACS_LLCORNER);
+ mvaddch(y-2, x+w, ACS_URCORNER);
+ mvaddch(y+1+h, x+w, ACS_LRCORNER);
+ /* print window title */
+ attroff(a->attrs);
+ attron(a->text_attrs);
+ mvprintw(y-2, x+(w/2)-((a->title_len+4)/2), "[ %s ]", a->title);
+ /* print windows text */
+ i = -1;
+ if (a->text) {
+ while ( a->text[++i] ) {
+ mvprintw(y+i, x+1, a->text[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);
+ if (a->window_func) {
+ attron(a->text_attrs);
+ a->window_func(win, a, timedout);
+ attroff(a->text_attrs);
+ }
+ }
+ 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);
+ char **adj_text = calloc(rows+2, sizeof(char *));
+ char *p_strtok, *tok;
+ const char sep[] = "\n";
+
+ if (rows > a->height) goto error;
+ p_strtok = strdup(text);
+ do {
+ tok = strsep(&p_strtok, sep);
+ if (strlen(tok) > a->width) {
+ strcpy(tok+a->width-3, "...");
+ *(tok+a->width) = '\0';
+ }
+ adj_text[i] = tok;
+ i++;
+ } while (rows > 0);
+ 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));
+}
+
+void
+set_txtwindow_color(struct txtwindow *a, chtype wnd, chtype txt)
+{
+ a->attrs = wnd;
+ a->text_attrs = txt;
+}
+
+void
+set_txtwindow_dim(struct txtwindow *a, unsigned int w, unsigned int h)
+{
+ a->width = w;
+ a->height = h;
+}
+
diff --git a/src/ui_txtwindow.h b/src/ui_txtwindow.h
new file mode 100644
index 0000000..1e1bc3f
--- /dev/null
+++ b/src/ui_txtwindow.h
@@ -0,0 +1,55 @@
+#ifndef UI_TXTWINDOW_H
+#define UI_TXTWINDOW_H 1
+
+#include <ncurses.h>
+
+#include "ui.h"
+
+#define INITIAL_TITLE_LEN 32
+
+#define set_txtwindow_active(wnd, activate) wnd->active = activate;
+
+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 *, bool);
+ chtype attrs;
+ chtype text_attrs;
+};
+
+typedef int (*window_func)(WINDOW *, struct txtwindow *, bool);
+
+struct txtwindow *
+init_txtwindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height, window_func cb_update);
+
+struct txtwindow *
+init_txtwindow_centered(unsigned int width, unsigned int height, 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);
+
+void
+set_txtwindow_color(struct txtwindow *a, chtype wnd, chtype txt);
+
+void
+set_txtwindow_pos(struct txtwindow *a, unsigned int x, unsigned int y);
+
+void
+set_txtwindow_dim(struct txtwindow *a, unsigned int w, unsigned int h);
+
+#endif
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..9350e8e
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,32 @@
+CFLAGS = -Wall -g
+LDFLAGS = -lpthread -lrt -lncurses
+CC = gcc
+SOURCES = $(wildcard *.c)
+BINARIES = $(patsubst %.c,%,$(SOURCES))
+DEPS = $(patsubst %.c,%.d,$(SOURCES))
+
+all: $(BINARIES)
+
+%: %.c
+ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $(patsubst %.c,%,$<)
+
+ipctest: ipctest.c ../src/ui_ipc.c
+ $(CC) $(CFLAGS) $(LDFLAGS) ipctest.c ../src/ui_ipc.c -o ipctest
+
+clean:
+ rm -f $(DEPS)
+ rm -f $(BINARIES)
+
+run: all
+ @echo "* running tests"
+ for test in $(patsubst %.c,%,$(SOURCES)); do \
+ echo -n "* running $${test}"; \
+ ./$${test} >/dev/null; \
+ if [ $$? -ne 0 ]; then \
+ echo " FAILED!"; \
+ else \
+ echo " OK!"; \
+ fi; \
+ done
+
+.PHONY: all install clean
diff --git a/tests/ipctest.c b/tests/ipctest.c
new file mode 100644
index 0000000..bd7c620
--- /dev/null
+++ b/tests/ipctest.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "semconfig.h"
+#include "../src/ui_ipc.h"
+
+
+
+int main(int argc, char **argv) {
+ int ret, c_status;
+ pid_t child;
+
+ ret = ui_ipc_init(1);
+
+ ret |= ui_ipc_sempost(SEM_BS);
+ ret |= ui_ipc_sempost(SEM_BS);
+ if ( (child = fork()) == 0 ) {
+ printf("child: wait (%d)\n", ui_ipc_getvalue(SEM_BS));
+ ret |= ui_ipc_semtrywait(SEM_BS);
+ ret |= ui_ipc_semtrywait(SEM_BS);
+ ret |= ui_ipc_semwait(SEM_BS);
+ printf("child: done (%d)\n", ui_ipc_getvalue(SEM_BS));
+ ret |= ui_ipc_sempost(SEM_BS);
+ exit( (ret == 0 ? 0 : ret) );
+ } else if (child > 0) {
+ usleep(100000);
+ printf("parent: post (%d)\n", ui_ipc_getvalue(SEM_BS));
+ ui_ipc_sempost(SEM_BS);
+ } else {
+ ret |= 1;
+ }
+
+ wait(&c_status);
+ ret |= ui_ipc_semtrywait(SEM_BS);
+ ui_ipc_free(1);
+ exit( c_status | ret );
+}
+
diff --git a/tests/mqtest.c b/tests/mqtest.c
new file mode 100644
index 0000000..f2808c8
--- /dev/null
+++ b/tests/mqtest.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <mqueue.h>
+
+#include <assert.h>
+
+
+static mqd_t mq_test;
+static mqd_t mq_recv;
+static const size_t bufsiz = 256;
+
+int main(int argc, char **argv)
+{
+ int c_stat;
+ struct mq_attr m_attr;
+ char buf[bufsiz], recv[bufsiz];
+ unsigned int prio;
+ ssize_t sz_recv;
+
+ memset(buf, '\0', bufsiz);
+ memset(recv, '\0', bufsiz);
+ if (argc > 1)
+ strncpy(buf, argv[1], bufsiz-1);
+
+ m_attr.mq_flags = 0;
+ m_attr.mq_msgsize = bufsiz;
+ m_attr.mq_maxmsg = 10;
+ m_attr.mq_curmsgs = 0;
+
+ mq_unlink("/testmq");
+ assert( (mq_test = mq_open( "/testmq", O_NONBLOCK | O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG, &m_attr )) != (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);
+
+ strcpy(buf, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ");
+ assert ( mq_send(mq_test, buf, bufsiz, 0) == 0 );
+ assert ( (sz_recv = mq_receive(mq_test, recv, bufsiz, &prio)) > 0 );
+
+ printf("SENT(%03lu bytes): %s\n", (long unsigned int) strlen(buf), buf);
+ printf("RECV(%03lu bytes): %s\n", (long unsigned int) sz_recv, recv);
+
+ memset(recv, '\0', bufsiz);
+ if (fork() > 0) {
+ assert( (mq_recv = mq_open( "/testmq", O_RDONLY, S_IRWXU | S_IRWXG, &m_attr )) != (mqd_t)-1 );
+ assert ( (sz_recv = mq_receive(mq_recv, recv, bufsiz, &prio)) > 0 );
+ printf("RECV(%03lu bytes): %s\n", (long unsigned int) sz_recv, recv);
+ return 0;
+ }
+ printf("SENT(%03lu bytes): %s\n", (long unsigned int) strlen(buf), buf);
+ assert ( mq_send(mq_test, buf, bufsiz, 0) == 0 );
+ wait(&c_stat);
+
+ return 0;
+}
+
diff --git a/tests/ncurses.c b/tests/ncurses.c
new file mode 100644
index 0000000..23ef28d
--- /dev/null
+++ b/tests/ncurses.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ncurses.h>
+#include <assert.h>
+
+
+static WINDOW *wnd;
+
+int
+main(void)
+{
+ assert( (wnd = initscr()) != NULL );
+ assert( start_color() == 0 );
+ assert( init_pair(1, COLOR_BLACK, COLOR_WHITE) == 0 );
+ assert( raw() == 0 );
+ assert( keypad(wnd, TRUE) == 0 );
+ assert( noecho() == 0 );
+ assert( cbreak() == 0 );
+ assert( printw("TESTEST") == 0 );
+ assert( refresh() == 0 );
+ assert( clear() == 0 );
+ assert( delwin(wnd) == 0 );
+ assert( endwin() == 0 );
+ return 0;
+}
diff --git a/tests/producer.c b/tests/producer.c
new file mode 100644
index 0000000..f1a568d
--- /dev/null
+++ b/tests/producer.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "semconfig.h"
+
+sem_t *mysem = NULL, *mycnt = NULL;
+pid_t child;
+
+
+int main(int argc, char **argv) {
+ int semval = 10;
+
+ if (argc == 2) {
+ semval = atoi(argv[1]);
+ }
+
+ if ( (mysem = sem_open(TESTSEM, O_CREAT, S_IRUSR | S_IWUSR, 0)) != NULL &&
+ (mycnt = sem_open(CNTSEM, O_CREAT, S_IRUSR | S_IWUSR, semval)) != NULL ) {
+ while (semval-- >= 0) {
+ usleep(250);
+ printf("producer: +1");
+ assert( sem_post(mysem) == 0 );
+ printf("remaining: %d\n", semval);
+ }
+ assert( sem_close(mysem) == 0 && sem_close(mycnt) == 0 );
+ } else {
+ exit(1);
+ }
+ exit(0);
+}
+
diff --git a/tests/producer_consumer.c b/tests/producer_consumer.c
new file mode 100644
index 0000000..104004a
--- /dev/null
+++ b/tests/producer_consumer.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "semconfig.h"
+
+sem_t *mysem = NULL, *mycnt = NULL;
+pid_t child;
+
+
+int main(int argc, char **argv) {
+ int semval = 0;
+
+ if ( (mysem = sem_open(TESTSEM, 0, S_IRUSR | S_IWUSR, 1)) != NULL &&
+ (mycnt = sem_open(CNTSEM, 0, S_IRUSR | S_IWUSR, 1)) != NULL ) {
+ assert( sem_getvalue(mycnt, &semval) == 0 );
+ printf("factory producing %d items\n", semval);
+
+ while ( semval-- >= 0 ) {
+ usleep(250);
+ LOG("consumer: -1");
+ assert( sem_wait(mysem) == 0 );
+ printf("remaining: %d\n", semval);
+ }
+ } else {
+ exit(1);
+ }
+ assert( sem_close(mysem) == 0 );
+ assert( sem_unlink(TESTSEM) == 0 && sem_unlink(CNTSEM) == 0 );
+
+ exit(0);
+}
+
diff --git a/tests/pthread.c b/tests/pthread.c
new file mode 100644
index 0000000..eed53a6
--- /dev/null
+++ b/tests/pthread.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <assert.h>
+
+
+static pthread_mutex_t testMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t testCond = PTHREAD_COND_INITIALIZER;
+
+static void
+mywait(int time_secs)
+{
+ struct timespec now;
+ int rt;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ now.tv_sec += time_secs;
+
+ assert( pthread_mutex_lock(&testMutex) == 0 );
+ rt = pthread_cond_timedwait(&testCond, &testMutex, &now);
+ assert( rt == ETIMEDOUT || rt == 0 );
+ assert( pthread_mutex_unlock(&testMutex) == 0 );
+ printf("Done.\n");
+}
+
+static void *
+fun(void *arg)
+{
+ printf("Thread wait ..\n");
+ mywait(1);
+ mywait(1);
+ return NULL;
+}
+
+int
+main(void)
+{
+ pthread_t thread;
+ void *ret;
+
+ assert( pthread_create(&thread, NULL, fun, NULL) == 0 );
+ usleep(50000);
+ assert( pthread_cond_signal(&testCond) == 0 );
+ printf("Mainthread: join\n");
+ assert( pthread_join(thread, &ret) == 0 );
+ return 0;
+}
diff --git a/tests/semconfig.h b/tests/semconfig.h
new file mode 100644
index 0000000..2878dbe
--- /dev/null
+++ b/tests/semconfig.h
@@ -0,0 +1,9 @@
+#ifndef CONFIG_H
+#define CONFIG_H 1
+
+#define LOG(text) printf("%s\n", text);
+#define CMD(cmd) LOG(cmd); cmd;
+#define TESTSEM "/testsem"
+#define CNTSEM "/testcnt"
+
+#endif
diff --git a/tests/semtest.c b/tests/semtest.c
new file mode 100644
index 0000000..fdecf2d
--- /dev/null
+++ b/tests/semtest.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "semconfig.h"
+
+
+sem_t *mysem = NULL;
+pid_t child;
+
+
+int main(int argc, char **argv) {
+ sem_unlink(TESTSEM);
+ if ( (mysem = sem_open(TESTSEM, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) != NULL ) {
+ if ( (child = fork()) == 0 ) {
+ /* child */
+ usleep(250);
+ LOG("child: sempost");
+ sem_post(mysem);
+ LOG("child: done");
+ usleep(250);
+ exit(0);
+ } else if (child > 0) {
+ /* parent */
+ LOG("parent: semwait");
+ sem_wait(mysem);
+ LOG("parent: waitpid");
+ waitpid(child, NULL, 0);
+ } else if (child < 0) {
+ perror("fork");
+ }
+ } else {
+ sem_close(mysem);
+ exit(1);
+ }
+
+ int sval;
+ assert ( sem_getvalue(mysem, &sval) == 0 );
+ assert (sval == 0);
+
+ sem_unlink(TESTSEM);
+ exit(0);
+}
+
diff --git a/tests/strsep.c b/tests/strsep.c
new file mode 100644
index 0000000..24564af
--- /dev/null
+++ b/tests/strsep.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+int main(int argc, char **argv)
+{
+ int i = 0;
+ char *tok, *p_tok;
+ static char **arr;
+
+ int arrsiz = 1000;
+ static char *delim;
+ static char *str;
+
+ if (argc == 1) {
+ printf("automatic test ..\n");
+ delim = strdup(" ");
+ str = strdup("this is a simple string, which should be extracted to 12 strings");
+ } else if (argc != 4) {
+ fprintf(stderr, "usage: %s [ARR_SIZ] [DELIM] [STRING]\n", argv[0]);
+ exit(1);
+ } else {
+ arrsiz = atoi(argv[1]);
+ delim = strdup(argv[2]);
+ str = strdup(argv[3]);
+ }
+
+ arr = calloc(arrsiz, sizeof(char *));
+ p_tok = str;
+ while ( (tok = strsep(&p_tok, delim)) != NULL ) {
+ arr[i] = tok;
+ i++;
+ }
+
+ i = 0;
+ while ( arr[i] != NULL ) {
+ printf("ARRAY[%d]: %s\n", i, arr[i]);
+ i++;
+ }
+
+ if (argc == 1) {
+ if (i == 12) {
+ return 0;
+ } else return -1;
+ }
+ return 0;
+}
diff --git a/ui.c b/ui.c
deleted file mode 100644
index 58cc226..0000000
--- a/ui.c
+++ /dev/null
@@ -1,337 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <string.h>
-#include <ncurses.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <signal.h>
-
-#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"
-
-#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 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 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;
-
-
-void
-register_ui_elt(ui_callback uicb, void *data, WINDOW *wnd)
-{
- struct nask_ui *tmp, *new;
-
- if (nui != NULL) {
- tmp = nui;
- while (tmp->next != NULL) {
- tmp = tmp->next;
- }
- }
- new = calloc(1, sizeof(struct nask_ui));
- new->ui_elt_cb = uicb;
- new->wnd = wnd;
- new->data = data;
- new->next = NULL;
- if (nui == NULL) {
- nui = new;
- nui->next = NULL;
- } else {
- tmp->next = new;
- }
-}
-
-void
-unregister_ui_elt(void *data)
-{
- struct nask_ui *cur = nui, *next, *before = NULL;
-
- 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;
- }
-}
-
-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->ui_elt_cb != NULL) {
- cur->ui_elt_cb(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;
-
- pthread_mutex_lock(&mtx_update);
- gettimeofday(&now, NULL);
- wait.tv_sec = now.tv_sec + UILOOP_TIMEOUT;
- wait.tv_nsec = now.tv_usec * 1000;
- do_ui_update(true);
- sem_post(&sem_rdy);
- while (active == true) {
- pthread_mutex_unlock(&mtx_busy);
- cnd_ret = pthread_cond_timedwait(&cnd_update, &mtx_update, &wait);
- if (cnd_ret == ETIMEDOUT) {
- wait.tv_sec += UILOOP_TIMEOUT;
- }
- pthread_mutex_lock(&mtx_busy);
- if (--atmout == 0) active = false;
- if (active == false) {
- break;
- }
- do_ui_update( (cnd_ret == ETIMEDOUT ? true : false) );
- }
- pthread_mutex_unlock(&mtx_busy);
- pthread_mutex_unlock(&mtx_update);
- return (NULL);
-}
-
-void
-ui_thrd_force_update(void)
-{
- pthread_cond_signal(&cnd_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);
- 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) {
- 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));
-}
-
-void
-stop_ui(void)
-{
- pthread_mutex_lock(&mtx_busy);
- active = false;
- pthread_mutex_unlock(&mtx_busy);
-}
-
-static int
-stop_ui_thrd(void)
-{
- stop_ui();
- return (pthread_join(thrd, NULL));
-}
-
-static int
-send_passwd(int fifo_fd, 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);
- }
-}
-
-static bool
-process_key(char key, struct input *a, WINDOW *win)
-{
- bool retval = true;
-
- atmout = APP_TIMEOUT;
- switch (key) {
- case UIKEY_ENTER:
- send_passwd(ffd, a->input, a->input_len);
- passwd_from_ui = true;
- retval = false;
- break;
- case UIKEY_BACKSPACE:
- del_input(win, a);
- break;
- case UIKEY_ESC:
- retval = false;
- ui_thrd_force_update();
- break;
- case UIKEY_DOWN:
- case UIKEY_UP:
- case UIKEY_LEFT:
- case UIKEY_RIGHT:
- break;
- default:
- add_input(win, a, key);
- }
- return (retval);
-}
-
-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
-infownd_update(WINDOW *win, struct txtwindow *tw)
-{
- return (0);
-}
-
-int
-do_ui(int fifo_fd)
-{
- struct input *pw_input;
- struct anic *heartbeat;
- struct statusbar *higher, *lower;
- struct txtwindow *infownd;
- char key = '\0';
- char *title;
-
- asprintf(&title, "/* %s-%s */", PKGNAME, VERSION);
- ffd = fifo_fd;
- if (sem_init(&sem_rdy, 0, 0) == -1) {
- perror("init semaphore");
- goto error;
- }
- init_ui();
- pw_input = init_input((unsigned int)(max_x / 2)-PASSWD_XRELPOS, (unsigned int)(max_y / 2)-PASSWD_YRELPOS, PASSWD_WIDTH, "PASSWORD: ", MAX_PASSWD_LEN, 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), NULL);
- lower = init_statusbar(max_y - 1, max_x, COLOR_PAIR(3), lower_statusbar_update);
- infownd = init_txtwindow(10, 10, 25, 8, COLOR_PAIR(3), infownd_update);
-
- register_input(NULL, pw_input);
- register_statusbar(higher);
- register_statusbar(lower);
- register_anic(heartbeat);
- activate_input(wnd_main, pw_input);
- set_statusbar_text(higher, title);
- if (run_ui_thrd() != 0) {
- goto error;
- }
- sem_wait(&sem_rdy);
- wtimeout(wnd_main, 1000);
- while (active == true) {
- if ((key = wgetch(wnd_main)) == '\0') {
- break;
- }
- if (key == -1) {
- continue;
- }
- pthread_mutex_lock(&mtx_busy);
- active = process_key(key, pw_input, wnd_main);
- activate_input(wnd_main, pw_input);
- do_ui_update(false);
- pthread_mutex_unlock(&mtx_busy);
- }
- stop_ui_thrd();
- 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_txtwindow(infownd);
- free_ui();
- return (DOUI_OK);
-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);
-}
-
diff --git a/ui.h b/ui.h
deleted file mode 100644
index 77a5bc9..0000000
--- a/ui.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef UI_H
-#define UI_H 1
-
-#include <ncurses.h>
-#include <stdint.h>
-
-#define MAX_PASSWD_LEN 128
-
-#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_PASSWD 3
-
-#define UILOOP_TIMEOUT 1
-
-#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 (*ui_callback)(WINDOW *, void *, bool);
-
-struct nask_ui {
- ui_callback ui_elt_cb;
- WINDOW *wnd;
- void *data;
- struct nask_ui *next;
-};
-
-void
-register_ui_elt(ui_callback uicb, void *data, WINDOW *wnd);
-
-void
-unregister_ui_elt(void *data);
-
-void
-ui_thrd_force_update(void);
-
-WINDOW *
-init_ui(void);
-
-void
-free_ui(void);
-
-int
-do_ui(int fifo_fd);
-
-void
-stop_ui(void);
-
-bool
-is_passwd_from_ui(void);
-
-#endif
diff --git a/ui_ani.c b/ui_ani.c
deleted file mode 100644
index d38e090..0000000
--- a/ui_ani.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#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)
-{
- register_ui_elt(anic_cb, (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 <ncurses.h>
-
-
-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_nwindow.c b/ui_nwindow.c
deleted file mode 100644
index 7098097..0000000
--- a/ui_nwindow.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include "ui.h"
-#include "ui_nwindow.h"
-
-
-struct txtwindow *
-init_txtwindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height, chtype 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->scrollable = false;
- a->title_len = INITIAL_TITLE_LEN;
- a->text_len = INITIAL_TEXT_LEN;
- a->title = calloc(a->title_len, sizeof(char));
- a->text = calloc(a->text_len, sizeof(char));
- a->attrs = attrs;
- a->window_func = cb_update;
- return (a);
-}
-
-void
-free_txtwindow(struct txtwindow *a)
-{
- if (a->text) {
- free(a->text);
- }
- if (a->title) {
- free(a->title);
- }
- free(a);
-}
-
-int
-txtwindow_cb(WINDOW *win, void *data, bool timedout)
-{
- struct txtwindow *a = (struct txtwindow *) data;
- return (UICB_OK);
-}
-
-void inline
-register_txtwindow(struct txtwindow *a)
-{
- register_ui_elt(txtwindow_cb, (void *) a, NULL);
-}
-
-static inline size_t
-__do_textcpy(char **p_dest, size_t sz_dest, const char *p_src, size_t sz_src)
-{
- if (sz_src > sz_dest) {
- *p_dest = (char *) realloc(*p_dest, sz_dest * sizeof(char));
- }
- memset(*p_dest, '\0', sz_dest);
- return sz_dest;
-}
-
-void
-set_txtwindow_text(struct txtwindow *a, const char *text)
-{
- size_t len = strlen(text);
-
- if (len > a->text_len) {
- a->text_len = __do_textcpy(&a->text, a->text_len, text, len);
- }
-}
diff --git a/ui_nwindow.h b/ui_nwindow.h
deleted file mode 100644
index 5a983f7..0000000
--- a/ui_nwindow.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef UI_TXTWINDOW_H
-#define UI_TXTWINDOW_H 1
-
-#include <ncurses.h>
-
-
-#define INITIAL_TITLE_LEN 32
-#define INITIAL_TEXT_LEN 128
-
-struct txtwindow {
- unsigned int y;
- unsigned int x;
- unsigned int width;
- unsigned int height;
- bool scrollable;
- char *title;
- size_t title_len;
- char *text;
- size_t text_len;
- int (*window_func)(WINDOW *, struct txtwindow *);
- chtype attrs;
-};
-
-typedef int (*window_func)(WINDOW *, struct txtwindow *);
-
-struct txtwindow *
-init_txtwindow(unsigned int, unsigned int y, unsigned int width, unsigned int height, chtype attrs, window_func cb_update);
-
-void
-free_txtwindow(struct txtwindow *a);
-
-int
-txtwindow_cb(WINDOW *win, void *data, bool timedout);
-
-void
-register_txtwindow(struct txtwindow *a);
-
-void
-set_txtwindow_text(struct txtwindow *a, const char *text);
-
-void
-set_txtwindow_scrollable(struct txtwindow *a, bool scrollable);
-
-#endif