Mercurial > projects > pwm
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 { |