aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..5f0d6e9
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,176 @@
+#include <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 <semaphore.h>
+#include <time.h>
+#include <mqueue.h>
+
+#include "config.h"
+#include "opt.h"
+
+#include "ui.h"
+#include "ui_ipc.h"
+#include "ui_ani.h"
+#include "ui_input.h"
+#include "ui_statusbar.h"
+
+#define MSG(msg_idx) msg_arr[msg_idx]
+
+
+enum msg_index {
+ MSG_BUSY_FD = 0,
+ MSG_BUSY,
+ MSG_NO_FIFO,
+ MSG_FIFO_ERR,
+ MSG_FIFO_BUSY,
+ MSG_CRYPTCMD_ERR,
+ MSG_NUM
+};
+static const char *msg_arr[] = { "Please wait, got a piped password ..",
+ "Please wait, busy ..",
+ "check_fifo: %s is not a FIFO\n",
+ "check_fifo: %s error(%d): %s\n",
+ "fifo: cryptcreate busy",
+ "cryptcreate error"
+ };
+
+
+static bool
+check_fifo(char *fifo_path)
+{
+ struct stat st;
+
+ if (mkfifo(fifo_path, S_IRUSR | S_IWUSR) == 0) {
+ return (true);
+ } else {
+ if (errno == EEXIST) {
+ if (stat(fifo_path, &st) == 0) {
+ if (S_ISFIFO(st.st_mode) == 1) {
+ return (true);
+ } else {
+ fprintf(stderr, MSG(MSG_NO_FIFO), fifo_path);
+ return (false);
+ }
+ }
+ }
+ }
+ fprintf(stderr, MSG(MSG_FIFO_ERR), fifo_path, errno, strerror(errno));
+ return (false);
+}
+
+int
+run_cryptcreate(char *pass, char *crypt_cmd)
+{
+ int retval;
+ char *cmd;
+
+ if (crypt_cmd == NULL || pass == NULL) return (-1);
+ asprintf(&cmd, "echo '%s' | %s", pass, crypt_cmd);
+ retval = system(cmd);
+ free(cmd);
+ return (retval);
+}
+
+void sigfunc(int signal)
+{
+ switch (signal) {
+ case SIGTERM:
+ case SIGINT:
+ ui_ipc_semtrywait(SEM_UI);
+ ui_ipc_semtrywait(SEM_IN);
+ break;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = EXIT_FAILURE, ffd = -1, c_status;
+ pid_t child;
+ char pbuf[IPC_MQSIZ+1];
+ struct timespec ts_sem_input;
+
+ signal(SIGINT, sigfunc);
+ signal(SIGTERM, sigfunc);
+
+ if ( clock_gettime(CLOCK_REALTIME, &ts_sem_input) == -1 ) {
+ fprintf(stderr, "%s: clock get time error: %d (%s)\n", argv[0], errno, strerror(errno));
+ goto error;
+ }
+
+ if (ui_ipc_init(1) != 0) {
+ fprintf(stderr, "%s: can not create semaphore/message queue: %d (%s)\n", argv[0], errno, strerror(errno));
+ goto error;
+ }
+
+ memset(pbuf, '\0', IPC_MQSIZ+1);
+ parse_cmd(argc, argv);
+ if (check_fifo(GETOPT(FIFO_PATH).str) == false) {
+ usage(argv[0]);
+ goto error;
+ }
+ if ((ffd = open(GETOPT(FIFO_PATH).str, O_NONBLOCK | O_RDWR)) < 0) {
+ fprintf(stderr, "%s: fifo '%s' error: %d (%s)\n", argv[0], GETOPT(FIFO_PATH).str, errno, strerror(errno));
+ goto error;
+ }
+
+ ui_ipc_sempost(SEM_UI);
+ if ((child = fork()) == 0) {
+ /* child */
+ if (ffd >= 0) close(ffd);
+ fclose(stderr);
+ /* Slave process: TUI */
+ if (ui_ipc_init(0) == 0) {
+ ui_ipc_semwait(SEM_BS);
+ do_ui();
+ }
+ exit(0);
+ } else if (child > 0) {
+ /* parent */
+ fclose(stdin);
+ fclose(stdout);
+ ui_ipc_sempost(SEM_BS);
+ ui_ipc_sempost(SEM_UI);
+ /* Master process: mainloop (read passwd from message queue or fifo and exec cryptcreate */
+ while ( ui_ipc_getvalue(SEM_UI) > 0 || ui_ipc_getvalue(SEM_IN) > 0 ) {
+ ui_ipc_sempost(SEM_BS);
+ if (read(ffd, pbuf, IPC_MQSIZ) >= 0) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY_FD), strlen(MSG(MSG_BUSY_FD)));
+ if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR), strlen(MSG(MSG_CRYPTCMD_ERR)));
+ }
+ } else if ( ui_ipc_msgrecv(MQ_PW, pbuf, IPC_MQSIZ) != (int)-1 ) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_BUSY), strlen(MSG(MSG_BUSY)));
+ if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) {
+ ui_ipc_msgsend(MQ_IF, MSG(MSG_CRYPTCMD_ERR), strlen(MSG(MSG_CRYPTCMD_ERR)));
+ }
+ ui_ipc_semwait(SEM_IN);
+ }
+ ui_ipc_semwait(SEM_BS);
+ usleep(100000);
+ waitpid(child, &c_status, WNOHANG);
+ if ( WIFSIGNALED(c_status) != 0 ) {
+ break;
+ }
+ }
+ wait(&c_status);
+ memset(pbuf, '\0', IPC_MQSIZ+1);
+ } else {
+ /* fork error */
+ perror("fork");
+ goto error;
+ }
+
+ ret = EXIT_SUCCESS;
+error:
+ if (ffd >= 0) close(ffd);
+ ui_ipc_free(1);
+ exit(ret);
+}