projects/pwm

changeset 20:efef93e54c5f

Automatically save the database when receiving a fatal signal
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Wed Sep 06 13:56:11 2017 +0200 (2017-09-06)
parents 5c6155c8e9b6
children ee4d36c85287
files pwfile.c pwfile.h pwm.1.xml pwm.c pwm.h
line diff
     1.1 --- a/pwfile.c	Fri Sep 01 22:33:41 2017 +0200
     1.2 +++ b/pwfile.c	Wed Sep 06 13:56:11 2017 +0200
     1.3 @@ -381,8 +381,8 @@
     1.4  	pws3_file_set_header_field(file, save_host_field);
     1.5  }
     1.6  
     1.7 -int
     1.8 -pwfile_write_file(struct pwm_ctx *ctx)
     1.9 +static int
    1.10 +write_file(struct pwm_ctx *ctx, const char *filename)
    1.11  {
    1.12  	int	retval = -1;
    1.13  	char	*tmpfilename = NULL;
    1.14 @@ -390,15 +390,7 @@
    1.15  	int	fd = -1;
    1.16  	FILE	*fp = NULL;
    1.17  
    1.18 -	/* update password file metadata */
    1.19 -	update_file_metadata(ctx->file);
    1.20 -
    1.21 -	/* make a backup copy of the existing password file */
    1.22 -	if (make_backup_copy(ctx->filename) != 0) {
    1.23 -		goto out;
    1.24 -	}
    1.25 -
    1.26 -	xasprintf(&tmpfilename, "%s.XXXXXX", ctx->filename);
    1.27 +	xasprintf(&tmpfilename, "%s.XXXXXX", filename);
    1.28  
    1.29  	/* create temporary file */
    1.30  	old_mode = umask(S_IRWXG | S_IRWXO);
    1.31 @@ -440,7 +432,7 @@
    1.32  	}
    1.33  	if (retval == 0) {
    1.34  		/* rename temporary file and overwrite existing file */
    1.35 -		if (rename(tmpfilename, ctx->filename) != 0) {
    1.36 +		if (rename(tmpfilename, filename) != 0) {
    1.37  			warn("rename");
    1.38  			retval = -1;
    1.39  		}
    1.40 @@ -450,6 +442,39 @@
    1.41  	}
    1.42  	free(tmpfilename);
    1.43  
    1.44 +	return (retval);
    1.45 +}
    1.46 +
    1.47 +int
    1.48 +pwfile_write_autosave_file(struct pwm_ctx *ctx)
    1.49 +{
    1.50 +	int	retval;
    1.51 +	char	*autosave_filename;
    1.52 +
    1.53 +	xasprintf(&autosave_filename, "%s/autosave.psafe3", ctx->dirname);
    1.54 +
    1.55 +	retval = write_file(ctx, autosave_filename);
    1.56 +
    1.57 +	free(autosave_filename);
    1.58 +
    1.59 +	return (retval);
    1.60 +}
    1.61 +
    1.62 +int
    1.63 +pwfile_write_file(struct pwm_ctx *ctx)
    1.64 +{
    1.65 +	int	retval;
    1.66 +
    1.67 +	/* update password file metadata */
    1.68 +	update_file_metadata(ctx->file);
    1.69 +
    1.70 +	/* make a backup copy of the existing password file */
    1.71 +	if (make_backup_copy(ctx->filename) != 0) {
    1.72 +		return (-1);
    1.73 +	}
    1.74 +
    1.75 +	retval = write_file(ctx, ctx->filename);
    1.76 +
    1.77  	ctx->unsaved_changes = !!retval;
    1.78  
    1.79  	return (retval);
     2.1 --- a/pwfile.h	Fri Sep 01 22:33:41 2017 +0200
     2.2 +++ b/pwfile.h	Wed Sep 06 13:56:11 2017 +0200
     2.3 @@ -74,6 +74,7 @@
     2.4  void		pwfile_destroy(struct pwm_ctx *);
     2.5  int		pwfile_read_file(struct pwm_ctx *, FILE *);
     2.6  int		pwfile_write_file(struct pwm_ctx *);
     2.7 +int		pwfile_write_autosave_file(struct pwm_ctx *);
     2.8  union list_item ** pwfile_create_list(struct pwm_ctx *);
     2.9  void		pwfile_destroy_list(union list_item **);
    2.10  struct metadata * pwfile_get_metadata(struct pwm_ctx *);
     3.1 --- a/pwm.1.xml	Fri Sep 01 22:33:41 2017 +0200
     3.2 +++ b/pwm.1.xml	Wed Sep 06 13:56:11 2017 +0200
     3.3 @@ -34,7 +34,7 @@
     3.4        <email>guido+pwm@berhoerster.name</email>
     3.5        <personblurb/>
     3.6      </author>
     3.7 -    <date>12 August, 2017</date>
     3.8 +    <date>6 September, 2017</date>
     3.9    </info>
    3.10    <refmeta>
    3.11      <refentrytitle>pwm</refentrytitle>
    3.12 @@ -611,6 +611,23 @@
    3.13      </variablelist>
    3.14    </refsect1>
    3.15    <refsect1>
    3.16 +    <title>Asynchronous Events</title>
    3.17 +    <variablelist>
    3.18 +      <varlistentry>
    3.19 +        <term><literal>SIGINT</literal></term>
    3.20 +        <term><literal>SIGHUP</literal></term>
    3.21 +        <term><literal>SIGTERM</literal></term>
    3.22 +        <listitem>
    3.23 +          <para>If there are changes since the database was last written and
    3.24 +          <command>pwm</command> is running in interactive mode, it
    3.25 +          automatically writes a copy of the current database to the file
    3.26 +          <filename>~/.pwm/autosave.psafe3</filename> which may be used for
    3.27 +          recovery later.</para>
    3.28 +        </listitem>
    3.29 +      </varlistentry>
    3.30 +    </variablelist>
    3.31 +  </refsect1>
    3.32 +  <refsect1>
    3.33      <title>Files</title>
    3.34      <variablelist>
    3.35        <varlistentry>
    3.36 @@ -619,6 +636,13 @@
    3.37            <para>default password database</para>
    3.38          </listitem>
    3.39        </varlistentry>
    3.40 +      <varlistentry>
    3.41 +        <term><filename>~/.pwm/autosave.psafe3</filename></term>
    3.42 +        <listitem>
    3.43 +          <para>automatic copy of the password database after receiving a fatal
    3.44 +          signal in interactive mode</para>
    3.45 +        </listitem>
    3.46 +      </varlistentry>
    3.47      </variablelist>
    3.48    </refsect1>
    3.49    <refsect1>
     4.1 --- a/pwm.c	Fri Sep 01 22:33:41 2017 +0200
     4.2 +++ b/pwm.c	Wed Sep 06 13:56:11 2017 +0200
     4.3 @@ -142,6 +142,9 @@
     4.4  			goto out;
     4.5  		case IO_EOF:	/* FALLTHROUGH */
     4.6  		case IO_SIGNAL:
     4.7 +			if (ctx->unsaved_changes) {
     4.8 +				pwfile_write_autosave_file(ctx);
     4.9 +			}
    4.10  			goto quit;
    4.11  		default:
    4.12  			fprintf(stderr, "unknown error\n");
    4.13 @@ -306,7 +309,6 @@
    4.14  	const char	*master_password_filename = NULL;
    4.15  	struct pwm_ctx	ctx = { 0 };
    4.16  	struct passwd	*passwd;
    4.17 -	char		*pwm_dirname = NULL;
    4.18  	FILE		*fp = NULL;
    4.19  
    4.20  	setprogname(argv[0]);
    4.21 @@ -355,19 +357,20 @@
    4.22  		goto out;
    4.23  	}
    4.24  
    4.25 +	passwd = getpwuid(getuid());
    4.26 +	if (passwd == NULL) {
    4.27 +		err(1, "getpwuid");
    4.28 +	}
    4.29 +	xasprintf(&ctx.dirname, "%s/.pwm", passwd->pw_dir);
    4.30 +
    4.31 +	/* create ~/.pwm directory if necessary */
    4.32 +	if ((mkdir(ctx.dirname, S_IRWXU) != 0) && (errno != EEXIST)) {
    4.33 +		warn("failed to create directory \"%s\"", ctx.dirname);
    4.34 +		goto out;
    4.35 +	}
    4.36 +
    4.37  	if (optind == argc) {
    4.38 -		passwd = getpwuid(getuid());
    4.39 -		if (passwd == NULL) {
    4.40 -			err(1, "getpwuid");
    4.41 -		}
    4.42 -		xasprintf(&pwm_dirname, "%s/.pwm", passwd->pw_dir);
    4.43 -		xasprintf(&ctx.filename, "%s/pwm.psafe3", pwm_dirname);
    4.44 -
    4.45 -		/* create ~/.pwm directory if necessary */
    4.46 -		if ((mkdir(pwm_dirname, S_IRWXU) != 0) && (errno != EEXIST)) {
    4.47 -			warn("failed to create directory \"%s\"", pwm_dirname);
    4.48 -			goto out;
    4.49 -		}
    4.50 +		xasprintf(&ctx.filename, "%s/pwm.psafe3", ctx.dirname);
    4.51  	} else if (optind + 1 == argc) {
    4.52  		ctx.filename = xstrdup(argv[optind++]);
    4.53  	} else {
    4.54 @@ -417,8 +420,8 @@
    4.55  		fclose(fp);
    4.56  	}
    4.57  	free(ctx.filename);
    4.58 +	free(ctx.dirname);
    4.59  	free(ctx.errmsg);
    4.60 -	free(pwm_dirname);
    4.61  
    4.62  	exit(status);
    4.63  }
     5.1 --- a/pwm.h	Fri Sep 01 22:33:41 2017 +0200
     5.2 +++ b/pwm.h	Wed Sep 06 13:56:11 2017 +0200
     5.3 @@ -46,6 +46,7 @@
     5.4  struct pwm_ctx {
     5.5  	const char	*prev_cmd;
     5.6  	char		*errmsg;
     5.7 +	char		*dirname;
     5.8  	char		*filename;
     5.9  	struct pws3_file *file;
    5.10  	struct record_id_tree *record_id_tree;