Mercurial > projects > pwm
diff pwm.c @ 19:5c6155c8e9b6
Handle signals
Handled signals are generally blocked and only unblocked when doing blocking
I/O, i.e. either when reading commands or printing results. A (possibly
queued) signal will then interrupt I/O and can be dealt with in the main loop.
author | Guido Berhoerster <guido+pwm@berhoerster.name> |
---|---|
date | Fri, 01 Sep 2017 22:33:41 +0200 |
parents | 1e39a251cbe9 |
children | efef93e54c5f |
line wrap: on
line diff
--- a/pwm.c Thu Aug 24 13:10:56 2017 +0200 +++ b/pwm.c Fri Sep 01 22:33:41 2017 +0200 @@ -41,22 +41,11 @@ #include "pwm.h" #include "cmd.h" +#include "io.h" #include "pwfile.h" #include "tok.h" #include "util.h" -#ifndef PWM_HISTORY_ENTRIES_MAX -#define PWM_HISTORY_ENTRIES_MAX 1024 -#endif /* !PWM_HISTORY_MAX */ - -#ifndef PWM_HISTORY_LINES_MAX -#define PWM_HISTORY_LINES_MAX 256 -#endif /* !PWM_HISTORY_LINES_MAX */ - -#ifndef PWM_HISTORY_MAX -#define PWM_HISTORY_MAX (PWM_HISTORY_LINES_MAX * PWM_LINE_MAX) -#endif /* !PWM_HISTORY_MAX */ - static void usage(void) { @@ -81,11 +70,34 @@ } } -static int -complete_nothing(WordCompletion *cpl, void *data, const char *line, - int word_end) +void +pwm_block_signals(void) { - return (0); + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGQUIT); + if (sigprocmask(SIG_BLOCK, &set, NULL) != 0) { + err(1, "sigprocmask"); + } +} + +void +pwm_unblock_signals(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGQUIT); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) { + err(1, "sigprocmask"); + } } static int @@ -94,9 +106,8 @@ int retval = -1; char prompt[8 + 2 + 1]; GetLine *gl = NULL; - char buf[PWM_LINE_MAX]; - char *line = buf; - int c; + char buf[PWM_LINE_MAX + 1]; + int io_retval; int argc = 0; char **argv = NULL; struct cmd *cmd; @@ -104,31 +115,41 @@ snprintf(prompt, sizeof (prompt), "%.*s> ", 8, getprogname()); + pwm_block_signals(); + /* initialize libtecla */ gl = new_GetLine(PWM_LINE_MAX, PWM_HISTORY_MAX); if (gl == NULL) { err(1, "new_GetLine"); } + gl_catch_blocked(gl); gl_limit_history(gl, PWM_HISTORY_LINES_MAX); /* disable default filename completion */ - gl_customize_completion(gl, NULL, complete_nothing); + gl_customize_completion(gl, NULL, io_gl_complete_nothing); for (;;) { + /* read next line */ cmd = NULL; - line = gl_get_line(gl, prompt, NULL, -1); - if (line == NULL) { - switch (gl_return_status(gl)) { - case GLR_EOF: - break; - case GLR_ERROR: - warnx("gl_get_line: %s", - gl_error_message(gl, NULL, 0)); - } + buf[0] = '\0'; + io_retval = io_get_line(gl, prompt, 1, NULL, 0, + sizeof (buf), buf); + switch (io_retval) { + case IO_OK: break; + case IO_TRUNCATED: + /* line was truncated in non-interactive mode */ + fprintf(stderr, "line too long\n"); + goto out; + case IO_EOF: /* FALLTHROUGH */ + case IO_SIGNAL: + goto quit; + default: + fprintf(stderr, "unknown error\n"); + goto quit; } /* tokenize line */ - switch (tok_tokenize(line, &argc, &argv)) { + switch (tok_tokenize(buf, &argc, &argv)) { case TOK_ERR_SYSTEM_ERROR: err(1, "tok_tokenize"); case TOK_ERR_UNTERMINATED_QUOTE: @@ -171,7 +192,9 @@ goto out; } break; - case CMD_QUIT: + case CMD_SIGNAL: + fprintf(stderr, "received signal, quitting\n"); + case CMD_QUIT: /* FALLTHROUGH */ goto quit; } ctx->prev_cmd = cmd->full_cmd; @@ -201,69 +224,22 @@ int pwm_read_password(struct pwm_ctx *ctx, int is_new_password) { - int retval = -1; - GetLine *gl = NULL; - char *line; - size_t len; - char password_buf[sizeof (ctx->password)] = { '\0' }; - - /* initialize libtecla */ - gl = new_GetLine(sizeof (password_buf) - 1, 0); - if (gl == NULL) { - err(1, "new_GetLine"); - } - /* disable default filename completion */ - gl_customize_completion(gl, NULL, complete_nothing); - gl_echo_mode(gl, 0); - - line = gl_get_line(gl, is_new_password ? "New password: " : - "Password: ", NULL, -1); - putchar('\n'); - if (line == NULL) { - if (gl_return_status(gl) == GLR_ERROR) { - errx(1, "gl_get_line: %s", gl_error_message(gl, NULL, - 0)); - } - goto out; - } - len = strlen(line); - if ((len > 0) && (line[len - 1] == '\n')) { - line[--len] = '\0'; + switch (io_get_password(is_new_password ? "New Password:" : + "Password:", is_new_password ? "Confirm Password:" : NULL, + sizeof (ctx->password), ctx->password)) { + case IO_OK: + return (0); + case IO_SIGNAL: + return (-2); + case IO_PASSWORD_EMPTY: + pwm_err(ctx, "password must not be empty"); + return (-1); + case IO_PASSWORD_MISMATCH: + pwm_err(ctx, "passwords do not match"); + return (-1); + default: + return (-1); } - if (len == 0) { - fprintf(stderr, "password must not be empty\n"); - goto out; - } - strcpy(password_buf, line); - - /* confirm the entered password entered */ - if (is_new_password) { - line = gl_get_line(gl, "Confirm password: ", NULL, -1); - putchar('\n'); - if (line == NULL) { - if (gl_return_status(gl) == GLR_ERROR) { - errx(1, "gl_get_line: %s", gl_error_message(gl, - NULL, 0)); - } - goto out; - } - len = strlen(line); - if ((len > 0) && (line[len - 1] == '\n')) { - line[--len] = '\0'; - } - if (strcmp(password_buf, line) != 0) { - fprintf(stderr, "passwords do not match\n"); - goto out; - } - } - - strcpy(ctx->password, password_buf); - retval = 0; - -out: - del_GetLine(gl); - - return (retval); } static int