comparison 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
comparison
equal deleted inserted replaced
18:1e39a251cbe9 19:5c6155c8e9b6
34 #include <string.h> 34 #include <string.h>
35 #include <time.h> 35 #include <time.h>
36 #include <unistd.h> 36 #include <unistd.h>
37 37
38 #include "cmd.h" 38 #include "cmd.h"
39 #include "io.h"
39 #include "pager.h" 40 #include "pager.h"
41 #include "proc.h"
40 #include "pw.h" 42 #include "pw.h"
41 #include "pwfile.h" 43 #include "pwfile.h"
42 #include "util.h" 44 #include "util.h"
43 45
44 #define TIME_FORMAT "%Y-%m-%dT%TZ" 46 #define TIME_FORMAT "%Y-%m-%dT%TZ"
220 if (argc != 1) { 222 if (argc != 1) {
221 return (CMD_USAGE); 223 return (CMD_USAGE);
222 } 224 }
223 225
224 if (ctx->errmsg != NULL) { 226 if (ctx->errmsg != NULL) {
225 printf("%s\n", ctx->errmsg); 227 if (io_printf("%s\n", ctx->errmsg) == IO_SIGNAL) {
226 } 228 return (CMD_SIGNAL);
227 printf("There are%sunsaved changes\n", ctx->unsaved_changes ? " " : 229 }
228 " no "); 230 }
231 if (io_printf("There are%sunsaved changes\n",
232 ctx->unsaved_changes ? " " : " no ") == IO_SIGNAL) {
233 return (CMD_SIGNAL);
234 }
229 235
230 return (CMD_STATUS); 236 return (CMD_STATUS);
231 } 237 }
232 238
233 static enum cmd_return 239 static enum cmd_return
234 cmd_info(struct pwm_ctx *ctx, int argc, char *argv[]) 240 cmd_info(struct pwm_ctx *ctx, int argc, char *argv[])
235 { 241 {
242 enum cmd_return retval;
236 struct metadata *metadata; 243 struct metadata *metadata;
237 struct pager *pager; 244 struct pager *pager;
238 struct tm *tm; 245 struct tm *tm;
239 char timebuf[TIME_SIZE]; 246 char timebuf[TIME_SIZE];
240 247
242 return (CMD_USAGE); 249 return (CMD_USAGE);
243 } 250 }
244 251
245 metadata = pwfile_get_metadata(ctx); 252 metadata = pwfile_get_metadata(ctx);
246 253
247 pager = pager_create(stdout); 254 pager = pager_create(STDOUT_FILENO);
248 pager_printf(pager, "Format: 0x%04x\n", metadata->version); 255 pager_printf(pager, "Format: 0x%04x\n", metadata->version);
249 if (metadata->user != NULL) { 256 if (metadata->user != NULL) {
250 pager_printf(pager, "User: %s\n", metadata->user); 257 pager_printf(pager, "User: %s\n", metadata->user);
251 } 258 }
252 if (metadata->user != NULL) { 259 if (metadata->user != NULL) {
256 pager_printf(pager, "Application: %s\n", metadata->application); 263 pager_printf(pager, "Application: %s\n", metadata->application);
257 } 264 }
258 tm = gmtime(&metadata->timestamp); 265 tm = gmtime(&metadata->timestamp);
259 strftime(timebuf, sizeof (timebuf), TIME_FORMAT, tm); 266 strftime(timebuf, sizeof (timebuf), TIME_FORMAT, tm);
260 pager_printf(pager, "Last Saved: %s\n", timebuf); 267 pager_printf(pager, "Last Saved: %s\n", timebuf);
261 pager_show(pager); 268 retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
262 pager_destroy(pager); 269 pager_destroy(pager);
263 270
264 pwfile_destroy_metadata(metadata); 271 pwfile_destroy_metadata(metadata);
265 272
266 return (CMD_OK); 273 return (retval);
267 } 274 }
268 275
269 static enum cmd_return 276 static enum cmd_return
270 cmd_list(struct pwm_ctx *ctx, int argc, char *argv[]) 277 cmd_list(struct pwm_ctx *ctx, int argc, char *argv[])
271 { 278 {
336 343
337 goto out; 344 goto out;
338 } 345 }
339 } 346 }
340 347
341 pager = pager_create(stdout); 348 pager = pager_create(STDOUT_FILENO);
342 list = pwfile_create_list(ctx); 349 list = pwfile_create_list(ctx);
343 for (j = 0; list[j] != NULL; j++) { 350 for (j = 0; list[j] != NULL; j++) {
344 if (list[j]->any.type == ITEM_TYPE_GROUP) { 351 if (list[j]->any.type == ITEM_TYPE_GROUP) {
345 pager_printf(pager, "[%s]\n", list[j]->group.group); 352 pager_printf(pager, "[%s]\n", list[j]->group.group);
346 } else { 353 } else {
361 list[j]->record.title : ""); 368 list[j]->record.title : "");
362 } 369 }
363 pwfile_destroy_record(record); 370 pwfile_destroy_record(record);
364 } 371 }
365 } 372 }
366 pager_show(pager); 373 retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
367
368 retval = CMD_OK;
369 374
370 out: 375 out:
371 pager_destroy(pager); 376 pager_destroy(pager);
372 377
373 if (group_re != NULL) { 378 if (group_re != NULL) {
631 if (pwfile_modify_record(ctx, id, 636 if (pwfile_modify_record(ctx, id,
632 &(struct record){ .password = password }) != 0) { 637 &(struct record){ .password = password }) != 0) {
633 pwm_err(ctx, "record %u does not exist", id); 638 pwm_err(ctx, "record %u does not exist", id);
634 goto out; 639 goto out;
635 } 640 }
641 retval = CMD_OK;
636 } else { 642 } else {
637 printf("%s\n", password); 643 retval = io_printf("%s\n", password);
638 } 644 }
639
640 retval = CMD_OK;
641 645
642 out: 646 out:
643 free(char_groupv); 647 free(char_groupv);
644 648
645 return (retval); 649 return (retval);
665 } 669 }
666 670
667 return (CMD_OK); 671 return (CMD_OK);
668 } 672 }
669 673
670 static void 674 static int
671 print_record(struct record *record, int fields[], int show_labels, FILE *fp) 675 print_record(struct record *record, int fields[], int show_labels, int fd)
672 { 676 {
673 struct pager *pager; 677 struct pager *pager;
674 struct tm *tm; 678 struct tm *tm;
675 char timebuf[TIME_SIZE]; 679 char timebuf[TIME_SIZE];
676 680 int retval;
677 pager = pager_create(fp); 681
682 pager = pager_create(fd);
678 if (fields[FIELD_TITLE]) { 683 if (fields[FIELD_TITLE]) {
679 pager_printf(pager, "%s%s\n", show_labels ? 684 pager_printf(pager, "%s%s\n", show_labels ?
680 field_labels[FIELD_TITLE] : "", (record->title != NULL) ? 685 field_labels[FIELD_TITLE] : "", (record->title != NULL) ?
681 record->title : ""); 686 record->title : "");
682 } 687 }
715 tm = gmtime(&record->mtime); 720 tm = gmtime(&record->mtime);
716 strftime(timebuf, sizeof (timebuf), TIME_FORMAT, tm); 721 strftime(timebuf, sizeof (timebuf), TIME_FORMAT, tm);
717 pager_printf(pager, "%s%s\n", show_labels ? 722 pager_printf(pager, "%s%s\n", show_labels ?
718 field_labels[FIELD_MTIME] : "", timebuf); 723 field_labels[FIELD_MTIME] : "", timebuf);
719 } 724 }
720 pager_show(pager); 725 retval = pager_show(pager);
721 pager_destroy(pager); 726 pager_destroy(pager);
727
728 return (retval);
722 } 729 }
723 730
724 static enum cmd_return 731 static enum cmd_return
725 cmd_show(struct pwm_ctx *ctx, int argc, char *argv[]) 732 cmd_show(struct pwm_ctx *ctx, int argc, char *argv[])
726 { 733 {
734 enum cmd_return retval;
727 unsigned int id; 735 unsigned int id;
728 struct record *record; 736 struct record *record;
729 int i; 737 int i;
730 enum field_type type; 738 enum field_type type;
731 int fields[COUNTOF(field_namev) - 1] = { 739 int fields[COUNTOF(field_namev) - 1] = {
765 record = pwfile_get_record(ctx, id); 773 record = pwfile_get_record(ctx, id);
766 if (record == NULL) { 774 if (record == NULL) {
767 pwm_err(ctx, "record %u does not exist", id); 775 pwm_err(ctx, "record %u does not exist", id);
768 return (CMD_ERR); 776 return (CMD_ERR);
769 } 777 }
770 print_record(record, fields, 1, stdout); 778 retval = (print_record(record, fields, 1, STDOUT_FILENO) != IO_SIGNAL) ?
779 CMD_OK : CMD_SIGNAL;
771 pwfile_destroy_record(record); 780 pwfile_destroy_record(record);
772 781
773 return (CMD_OK); 782 return (retval);
774 } 783 }
775 784
776 static enum cmd_return 785 static enum cmd_return
777 cmd_pipe(struct pwm_ctx *ctx, int argc, char *argv[]) 786 cmd_pipe(struct pwm_ctx *ctx, int argc, char *argv[])
778 { 787 {
779 enum cmd_return retval = CMD_ERR; 788 enum cmd_return retval = CMD_ERR;
780 unsigned int id; 789 unsigned int id;
781 struct record *record = NULL; 790 struct record *record = NULL;
782 enum field_type type; 791 enum field_type type;
783 int fields[COUNTOF(field_namev) - 1] = { 0 }; 792 int fields[COUNTOF(field_namev) - 1] = { 0 };
784 FILE *fp = NULL; 793 struct proc proc = { 0 };
785 794
786 if (argc != 4) { 795 if (argc != 4) {
787 return (CMD_USAGE); 796 return (CMD_USAGE);
788 } 797 }
789 798
797 pwm_err(ctx, "bad field name \"%s\"", argv[2]); 806 pwm_err(ctx, "bad field name \"%s\"", argv[2]);
798 return (CMD_ERR); 807 return (CMD_ERR);
799 } 808 }
800 fields[type] = 1; 809 fields[type] = 1;
801 810
802 fp = popen(argv[3], "w"); 811 if (proc_open(&proc, argv[3], "w") != IO_OK) {
803 if (fp == NULL) {
804 warn("popen");
805 goto out; 812 goto out;
806 } 813 }
807 814
808 record = pwfile_get_record(ctx, id); 815 record = pwfile_get_record(ctx, id);
809 if (record == NULL) { 816 if (record == NULL) {
810 pwm_err(ctx, "record %u does not exist", id); 817 pwm_err(ctx, "record %u does not exist", id);
811 goto out; 818 goto out;
812 } 819 }
813 820
814 print_record(record, fields, 0, fp); 821 retval = (print_record(record, fields, 0, proc.fd) != IO_SIGNAL) ?
815 822 CMD_OK : CMD_SIGNAL;
816 retval = CMD_OK;
817 823
818 out: 824 out:
819 pwfile_destroy_record(record); 825 pwfile_destroy_record(record);
820 if (fp != NULL) { 826 if (proc.pid != 0) {
821 pclose(fp); 827 if (proc_close(&proc) == IO_SIGNAL) {
828 retval = CMD_SIGNAL;
829 }
822 } 830 }
823 831
824 return (retval); 832 return (retval);
825 } 833 }
826 834
881 } 889 }
882 890
883 static enum cmd_return 891 static enum cmd_return
884 cmd_help(struct pwm_ctx *ctx, int argc, char *argv[]) 892 cmd_help(struct pwm_ctx *ctx, int argc, char *argv[])
885 { 893 {
894 enum cmd_return retval = CMD_OK;
886 struct pager *pager; 895 struct pager *pager;
887 struct cmd *cmd; 896 struct cmd *cmd;
888 897
889 if (argc > 2) { 898 if (argc > 2) {
890 return (CMD_USAGE); 899 return (CMD_USAGE);
891 } 900 }
892 901
893 pager = pager_create(stdout); 902 pager = pager_create(STDOUT_FILENO);
894 if (argc == 2) { 903 if (argc == 2) {
895 for (cmd = cmds; cmd->cmd_func != NULL; cmd++) { 904 for (cmd = cmds; cmd->cmd_func != NULL; cmd++) {
896 if ((strcmp(argv[1], cmd->abbrev_cmd) == 0) || 905 if ((strcmp(argv[1], cmd->abbrev_cmd) == 0) ||
897 (strcmp(argv[1], cmd->full_cmd) == 0)) { 906 (strcmp(argv[1], cmd->full_cmd) == 0)) {
898 pager_printf(pager, "%s\n", cmd->usage); 907 pager_printf(pager, "%s\n", cmd->usage);
904 for (cmd = cmds; cmd->cmd_func != NULL; cmd++) { 913 for (cmd = cmds; cmd->cmd_func != NULL; cmd++) {
905 pager_printf(pager, "%-2s %-16s %s\n", cmd->abbrev_cmd, 914 pager_printf(pager, "%-2s %-16s %s\n", cmd->abbrev_cmd,
906 cmd->full_cmd, cmd->description); 915 cmd->full_cmd, cmd->description);
907 } 916 }
908 } 917 }
909 pager_show(pager); 918 retval = (pager_show(pager) != IO_SIGNAL) ? CMD_OK : CMD_SIGNAL;
910 pager_destroy(pager); 919 pager_destroy(pager);
911 920
912 return (CMD_OK); 921 return (retval);
913 } 922 }
914 923
915 static enum cmd_return 924 static enum cmd_return
916 cmd_write(struct pwm_ctx *ctx, int argc, char *argv[]) 925 cmd_write(struct pwm_ctx *ctx, int argc, char *argv[])
917 { 926 {