# HG changeset patch # User Guido Berhoerster # Date 1504698971 -7200 # Node ID efef93e54c5fd9344e02b459bf73731b526486ba # Parent 5c6155c8e9b68169ed049160274dc6141e92fcce Automatically save the database when receiving a fatal signal diff -r 5c6155c8e9b6 -r efef93e54c5f pwfile.c --- a/pwfile.c Fri Sep 01 22:33:41 2017 +0200 +++ b/pwfile.c Wed Sep 06 13:56:11 2017 +0200 @@ -381,8 +381,8 @@ pws3_file_set_header_field(file, save_host_field); } -int -pwfile_write_file(struct pwm_ctx *ctx) +static int +write_file(struct pwm_ctx *ctx, const char *filename) { int retval = -1; char *tmpfilename = NULL; @@ -390,15 +390,7 @@ int fd = -1; FILE *fp = NULL; - /* update password file metadata */ - update_file_metadata(ctx->file); - - /* make a backup copy of the existing password file */ - if (make_backup_copy(ctx->filename) != 0) { - goto out; - } - - xasprintf(&tmpfilename, "%s.XXXXXX", ctx->filename); + xasprintf(&tmpfilename, "%s.XXXXXX", filename); /* create temporary file */ old_mode = umask(S_IRWXG | S_IRWXO); @@ -440,7 +432,7 @@ } if (retval == 0) { /* rename temporary file and overwrite existing file */ - if (rename(tmpfilename, ctx->filename) != 0) { + if (rename(tmpfilename, filename) != 0) { warn("rename"); retval = -1; } @@ -450,6 +442,39 @@ } free(tmpfilename); + return (retval); +} + +int +pwfile_write_autosave_file(struct pwm_ctx *ctx) +{ + int retval; + char *autosave_filename; + + xasprintf(&autosave_filename, "%s/autosave.psafe3", ctx->dirname); + + retval = write_file(ctx, autosave_filename); + + free(autosave_filename); + + return (retval); +} + +int +pwfile_write_file(struct pwm_ctx *ctx) +{ + int retval; + + /* update password file metadata */ + update_file_metadata(ctx->file); + + /* make a backup copy of the existing password file */ + if (make_backup_copy(ctx->filename) != 0) { + return (-1); + } + + retval = write_file(ctx, ctx->filename); + ctx->unsaved_changes = !!retval; return (retval); diff -r 5c6155c8e9b6 -r efef93e54c5f pwfile.h --- a/pwfile.h Fri Sep 01 22:33:41 2017 +0200 +++ b/pwfile.h Wed Sep 06 13:56:11 2017 +0200 @@ -74,6 +74,7 @@ void pwfile_destroy(struct pwm_ctx *); int pwfile_read_file(struct pwm_ctx *, FILE *); int pwfile_write_file(struct pwm_ctx *); +int pwfile_write_autosave_file(struct pwm_ctx *); union list_item ** pwfile_create_list(struct pwm_ctx *); void pwfile_destroy_list(union list_item **); struct metadata * pwfile_get_metadata(struct pwm_ctx *); diff -r 5c6155c8e9b6 -r efef93e54c5f pwm.1.xml --- a/pwm.1.xml Fri Sep 01 22:33:41 2017 +0200 +++ b/pwm.1.xml Wed Sep 06 13:56:11 2017 +0200 @@ -34,7 +34,7 @@ guido+pwm@berhoerster.name - 12 August, 2017 + 6 September, 2017 pwm @@ -611,6 +611,23 @@ + Asynchronous Events + + + SIGINT + SIGHUP + SIGTERM + + If there are changes since the database was last written and + pwm is running in interactive mode, it + automatically writes a copy of the current database to the file + ~/.pwm/autosave.psafe3 which may be used for + recovery later. + + + + + Files @@ -619,6 +636,13 @@ default password database + + ~/.pwm/autosave.psafe3 + + automatic copy of the password database after receiving a fatal + signal in interactive mode + + diff -r 5c6155c8e9b6 -r efef93e54c5f pwm.c --- a/pwm.c Fri Sep 01 22:33:41 2017 +0200 +++ b/pwm.c Wed Sep 06 13:56:11 2017 +0200 @@ -142,6 +142,9 @@ goto out; case IO_EOF: /* FALLTHROUGH */ case IO_SIGNAL: + if (ctx->unsaved_changes) { + pwfile_write_autosave_file(ctx); + } goto quit; default: fprintf(stderr, "unknown error\n"); @@ -306,7 +309,6 @@ const char *master_password_filename = NULL; struct pwm_ctx ctx = { 0 }; struct passwd *passwd; - char *pwm_dirname = NULL; FILE *fp = NULL; setprogname(argv[0]); @@ -355,19 +357,20 @@ goto out; } + passwd = getpwuid(getuid()); + if (passwd == NULL) { + err(1, "getpwuid"); + } + xasprintf(&ctx.dirname, "%s/.pwm", passwd->pw_dir); + + /* create ~/.pwm directory if necessary */ + if ((mkdir(ctx.dirname, S_IRWXU) != 0) && (errno != EEXIST)) { + warn("failed to create directory \"%s\"", ctx.dirname); + goto out; + } + if (optind == argc) { - passwd = getpwuid(getuid()); - if (passwd == NULL) { - err(1, "getpwuid"); - } - xasprintf(&pwm_dirname, "%s/.pwm", passwd->pw_dir); - xasprintf(&ctx.filename, "%s/pwm.psafe3", pwm_dirname); - - /* create ~/.pwm directory if necessary */ - if ((mkdir(pwm_dirname, S_IRWXU) != 0) && (errno != EEXIST)) { - warn("failed to create directory \"%s\"", pwm_dirname); - goto out; - } + xasprintf(&ctx.filename, "%s/pwm.psafe3", ctx.dirname); } else if (optind + 1 == argc) { ctx.filename = xstrdup(argv[optind++]); } else { @@ -417,8 +420,8 @@ fclose(fp); } free(ctx.filename); + free(ctx.dirname); free(ctx.errmsg); - free(pwm_dirname); exit(status); } diff -r 5c6155c8e9b6 -r efef93e54c5f pwm.h --- a/pwm.h Fri Sep 01 22:33:41 2017 +0200 +++ b/pwm.h Wed Sep 06 13:56:11 2017 +0200 @@ -46,6 +46,7 @@ struct pwm_ctx { const char *prev_cmd; char *errmsg; + char *dirname; char *filename; struct pws3_file *file; struct record_id_tree *record_id_tree;