#include "config.h" #include #include #include #include #include #include #include #include #include #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" #include "ui_nask.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; #ifdef DEBUG if (asprintf(&cmd, "echo '%s' | %s 1>&2", pass, crypt_cmd) < 0) #else if (asprintf(&cmd, "echo '%s' | %s >/dev/null 2>/dev/null", pass, crypt_cmd) < 0) #endif return -2; retval = system(cmd); free(cmd); return (retval); } void sigfunc(int signal) { switch (signal) { case SIGSEGV: case SIGTERM: ui_ipc_semtrywait(SEM_UI); break; } } int main(int argc, char **argv) { int ret = EXIT_FAILURE, ffd = -1, c_status; pid_t child; char pbuf[IPC_MQSIZ+1]; bool csetup_ok = false; signal(SIGINT, SIG_IGN); signal(SIGTERM, sigfunc); if ( parse_cmd(argc, argv) != 0 ) exit(EXIT_FAILURE); 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; } 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); log_init( GETOPT(LOG_FILE).str ); logs("%s\n", "log init"); logs_dbg("%s\n", "debug mode active"); ui_ipc_sempost(SEM_UI); ui_ipc_sempost(SEM_IN); if ((child = fork()) == 0) { /* child */ logs("%s\n", "child"); if (ffd >= 0) close(ffd); #ifndef DEBUG fclose(stderr); #endif /* Slave process: TUI */ if (ui_ipc_init(0) == 0) { do_ui(); } ui_ipc_free(0); 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 */ while ( ui_ipc_getvalue(SEM_UI) > 0 ) { if (read(ffd, pbuf, IPC_MQSIZ) >= 0) { ui_ipc_semwait(SEM_IN); logs_dbg("%s\n", "fifo password"); if (run_cryptcreate(pbuf, GETOPT(CRYPT_CMD).str) != 0) { logs_dbg("%s\n", "cryptcreate error"); sleep(3); } else { csetup_ok = true; logs_dbg("%s\n", "cryptcreate success"); ui_ipc_semtrywait(SEM_UI); } ui_ipc_sempost(SEM_IN); } else if ( ui_ipc_msgcount(MQ_PW) > 0 ) { //ui_ipc_semwait(SEM_IN); ui_ipc_msgrecv(MQ_PW, pbuf, 0); 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 { csetup_ok = true; logs_dbg("%s\n", "cryptcreate success"); ui_ipc_semtrywait(SEM_UI); } //ui_ipc_sempost(SEM_IN); } usleep(100000); } logs("%s\n", "waiting for child"); wait(&c_status); memset(pbuf, '\0', IPC_MQSIZ+1); } else { /* fork error */ perror("fork"); goto error; } if (csetup_ok) ret = EXIT_SUCCESS; else ret = EXIT_FAILURE; ui_ipc_free(1); error: logs("%s\n", "exiting .."); if (ffd >= 0) close(ffd); log_free(); exit(ret); }