Mercurial > projects > pwm
changeset 20:efef93e54c5f
Automatically save the database when receiving a fatal signal
author | Guido Berhoerster <guido+pwm@berhoerster.name> |
---|---|
date | Wed, 06 Sep 2017 13:56:11 +0200 |
parents | 5c6155c8e9b6 |
children | ee4d36c85287 |
files | pwfile.c pwfile.h pwm.1.xml pwm.c pwm.h |
diffstat | 5 files changed, 81 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- 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);
--- 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 *);
--- 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 @@ <email>guido+pwm@berhoerster.name</email> <personblurb/> </author> - <date>12 August, 2017</date> + <date>6 September, 2017</date> </info> <refmeta> <refentrytitle>pwm</refentrytitle> @@ -611,6 +611,23 @@ </variablelist> </refsect1> <refsect1> + <title>Asynchronous Events</title> + <variablelist> + <varlistentry> + <term><literal>SIGINT</literal></term> + <term><literal>SIGHUP</literal></term> + <term><literal>SIGTERM</literal></term> + <listitem> + <para>If there are changes since the database was last written and + <command>pwm</command> is running in interactive mode, it + automatically writes a copy of the current database to the file + <filename>~/.pwm/autosave.psafe3</filename> which may be used for + recovery later.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1> <title>Files</title> <variablelist> <varlistentry> @@ -619,6 +636,13 @@ <para>default password database</para> </listitem> </varlistentry> + <varlistentry> + <term><filename>~/.pwm/autosave.psafe3</filename></term> + <listitem> + <para>automatic copy of the password database after receiving a fatal + signal in interactive mode</para> + </listitem> + </varlistentry> </variablelist> </refsect1> <refsect1>
--- 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); }