diff cmd.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 ec01c579024a
line wrap: on
line diff
--- a/cmd.c	Thu Aug 24 13:10:56 2017 +0200
+++ b/cmd.c	Fri Sep 01 22:33:41 2017 +0200
@@ -36,7 +36,9 @@
 #include <unistd.h>
 
 #include "cmd.h"
+#include "io.h"
 #include "pager.h"
+#include "proc.h"
 #include "pw.h"
 #include "pwfile.h"
 #include "util.h"
@@ -222,10 +224,14 @@
 	}
 
 	if (ctx->errmsg != NULL) {
-		printf("%s\n", ctx->errmsg);
+		if (io_printf("%s\n", ctx->errmsg) == IO_SIGNAL) {
+			return (CMD_SIGNAL);
+		}
 	}
-	printf("There are%sunsaved changes\n", ctx->unsaved_changes ? " " :
-	    " no ");
+	if (io_printf("There are%sunsaved changes\n",
+	    ctx->unsaved_changes ? " " : " no ") == IO_SIGNAL) {
+		return (CMD_SIGNAL);
+	}
 
 	return (CMD_STATUS);
 }
@@ -233,6 +239,7 @@
 static enum cmd_return
 cmd_info(struct pwm_ctx *ctx, int argc, char *argv[])
 {
+	enum cmd_return	retval;
 	struct metadata	*metadata;
 	struct pager	*pager;
 	struct tm	*tm;
@@ -244,7 +251,7 @@
 
 	metadata = pwfile_get_metadata(ctx);
 
-	pager = pager_create(stdout);
+	pager = pager_create(STDOUT_FILENO);
 	pager_printf(pager, "Format:      0x%04x\n", metadata->version);
 	if (metadata->user != NULL) {
 		pager_printf(pager, "User:        %s\n", metadata->user);
@@ -258,12 +265,12 @@
 	tm = gmtime(&metadata->timestamp);
 	strftime(timebuf, sizeof (timebuf), TIME_FORMAT, tm);
 	pager_printf(pager, "Last Saved:  %s\n", timebuf);
-	pager_show(pager);
+	retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
 	pager_destroy(pager);
 
 	pwfile_destroy_metadata(metadata);
 
-	return (CMD_OK);
+	return (retval);
 }
 
 static enum cmd_return
@@ -338,7 +345,7 @@
 		}
 	}
 
-	pager = pager_create(stdout);
+	pager = pager_create(STDOUT_FILENO);
 	list = pwfile_create_list(ctx);
 	for (j = 0; list[j] != NULL; j++) {
 		if (list[j]->any.type == ITEM_TYPE_GROUP) {
@@ -363,9 +370,7 @@
 			pwfile_destroy_record(record);
 		}
 	}
-	pager_show(pager);
-
-	retval = CMD_OK;
+	retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
 
 out:
 	pager_destroy(pager);
@@ -633,12 +638,11 @@
 			pwm_err(ctx, "record %u does not exist", id);
 			goto out;
 		}
+		retval = CMD_OK;
 	} else {
-		printf("%s\n", password);
+		retval = io_printf("%s\n", password);
 	}
 
-	retval = CMD_OK;
-
 out:
 	free(char_groupv);
 
@@ -667,14 +671,15 @@
 	return (CMD_OK);
 }
 
-static void
-print_record(struct record *record, int fields[], int show_labels, FILE *fp)
+static int
+print_record(struct record *record, int fields[], int show_labels, int fd)
 {
 	struct pager	*pager;
 	struct tm	*tm;
 	char		timebuf[TIME_SIZE];
+	int		retval;
 
-	pager = pager_create(fp);
+	pager = pager_create(fd);
 	if (fields[FIELD_TITLE]) {
 		pager_printf(pager, "%s%s\n", show_labels ?
 		    field_labels[FIELD_TITLE] : "", (record->title != NULL) ?
@@ -717,13 +722,16 @@
 		pager_printf(pager, "%s%s\n", show_labels ?
 		    field_labels[FIELD_MTIME] : "", timebuf);
 	}
-	pager_show(pager);
+	retval = pager_show(pager);
 	pager_destroy(pager);
+
+	return (retval);
 }
 
 static enum cmd_return
 cmd_show(struct pwm_ctx *ctx, int argc, char *argv[])
 {
+	enum cmd_return	retval;
 	unsigned int	id;
 	struct record	*record;
 	int		i;
@@ -767,10 +775,11 @@
 		pwm_err(ctx, "record %u does not exist", id);
 		return (CMD_ERR);
 	}
-	print_record(record, fields, 1, stdout);
+	retval = (print_record(record, fields, 1, STDOUT_FILENO) != IO_SIGNAL) ?
+	    CMD_OK : CMD_SIGNAL;
 	pwfile_destroy_record(record);
 
-	return (CMD_OK);
+	return (retval);
 }
 
 static enum cmd_return
@@ -781,7 +790,7 @@
 	struct record	*record = NULL;
 	enum field_type	type;
 	int		fields[COUNTOF(field_namev) - 1] = { 0 };
-	FILE		*fp = NULL;
+	struct proc	proc = { 0 };
 
 	if (argc != 4) {
 		return (CMD_USAGE);
@@ -799,9 +808,7 @@
 	}
 	fields[type] = 1;
 
-	fp = popen(argv[3], "w");
-	if (fp == NULL) {
-		warn("popen");
+	if (proc_open(&proc, argv[3], "w") != IO_OK) {
 		goto out;
 	}
 
@@ -811,14 +818,15 @@
 		goto out;
 	}
 
-	print_record(record, fields, 0, fp);
-
-	retval = CMD_OK;
+	retval = (print_record(record, fields, 0, proc.fd) != IO_SIGNAL) ?
+	    CMD_OK : CMD_SIGNAL;
 
 out:
 	pwfile_destroy_record(record);
-	if (fp != NULL) {
-		pclose(fp);
+	if (proc.pid != 0) {
+		if (proc_close(&proc) == IO_SIGNAL) {
+			retval = CMD_SIGNAL;
+		}
 	}
 
 	return (retval);
@@ -883,6 +891,7 @@
 static enum cmd_return
 cmd_help(struct pwm_ctx *ctx, int argc, char *argv[])
 {
+	enum cmd_return	retval = CMD_OK;
 	struct pager	*pager;
 	struct cmd	*cmd;
 
@@ -890,7 +899,7 @@
 		return (CMD_USAGE);
 	}
 
-	pager = pager_create(stdout);
+	pager = pager_create(STDOUT_FILENO);
 	if (argc == 2) {
 		for (cmd = cmds; cmd->cmd_func != NULL; cmd++) {
 			if ((strcmp(argv[1], cmd->abbrev_cmd) == 0) ||
@@ -906,10 +915,10 @@
 			    cmd->full_cmd, cmd->description);
 		}
 	}
-	pager_show(pager);
+	retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
 	pager_destroy(pager);
 
-	return (CMD_OK);
+	return (retval);
 }
 
 static enum cmd_return