aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/DETAILS101
-rw-r--r--doc/HACKING4
-rw-r--r--doc/gpg.sgml9
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/export.c2
-rw-r--r--g10/g10.c2
-rw-r--r--g10/keygen.c308
-rw-r--r--util/ChangeLog4
-rw-r--r--util/argparse.c2
11 files changed, 389 insertions, 57 deletions
diff --git a/NEWS b/NEWS
index ae91562f5..ac2723890 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
Noteworthy changes in the current test release
----------------------------------------------
+ * Add an experimental feature to do unattended key generation.
+
* The user is now asked for the reason of revocation as required
by the new OpenPGP draft.
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 06008a3aa..bdd535e5c 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2000-03-09 15:01:51 Werner Koch ([email protected])
+
+ * DETAILS: Ad a short blurb about unattended key generation.
+
Wed Feb 9 15:33:44 CET 2000 Werner Koch <[email protected]>
* gpg.sgml: Describe --ignore-time-conflict.
diff --git a/doc/DETAILS b/doc/DETAILS
index 0ab83ecdf..37475c6b5 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -231,6 +231,107 @@ Key generation
Crypto '97 proceedings p. 260.
+Unattended key generation
+=========================
+There is an experimental feature which allows for unattended
+generation of keys controlled by a parameter file.
+This feature is not very well tested and does only make sense for some
+very special applications. Please don't complain if we decide to chnage
+the behaviour of this command.
+
+To use this feature, you use --gen-key together with --batch and feed the
+parameters either form stdin or from a file given on the commandline.
+The format of this file is as follows:
+ o Text only, line length is limited to about 1000 chars.
+ o You must use UTF-8 encoding to specifiy non-ascii characters.
+ o Empty lines are ignored
+ o Leading and trailing spaces are ignored
+ o A hash sign as the first non white space character indicates a comment line
+ o Control statements are indicated by a leading percent sign, the
+ arguments are separated by white space from the keyword.
+ o Parameters are specified by a keyword, followed by a colon. Arguments
+ are speparated by white space.
+ o The first parameter must be "Key-Type", control statements
+ may be placed anywhere.
+ o Key generation takes place when either the end of the parameter file
+ is reached, the next "Key-Type" parameter is encountered or at the
+ controlstatement "%commit"
+ o Control staements:
+ %echo <text>
+ Print <text>
+ %dry-run
+ Suppress actual key generation (useful for syntax checking)
+ %commit
+ Perform the key generation. An implicit commit is done
+ at the next "Key-Type" parameter.
+ %pubring <filename>
+ %secring <filename>
+ Do not write the key to the default or commandline given
+ keyring but to <filename>. This must be given before the first
+ commit to take place, duplicate specification of the same filename
+ is ignored, the last filename before a commit is used.
+ The filename is used until a new filename is used (at commit points)
+ and all keys are written to that file. If a new filename is given,
+ this file is created (and overwrites an existing one).
+ Both control statements must be given.
+ o The order of the parameters does not matter except for "Key-Type"
+ which must be the first parameter. The paramtyers are only for the
+ generated keyblock and paramters from previous key generations are not
+ used. Some syntactically checks may be performed.
+ The currently defined parameters are:
+ Key-Type: <algo-number>|<algo-string>
+ Starts a new parameter block by giving the type of the
+ primary key. The algorithm must be capable of signing.
+ This is a required parameter.
+ Key-Length: <length-in-bits>
+ Length of the key in bits. Default is 1024
+ Subkey-Type: <algo-number>|<algo-string>
+ This generates a secondary key. Currently only one subkey
+ can be handled.
+ Subkey-Length: <length-in-bits>
+ Length of the subkey in bits. Default is 1024.
+ Passphrase: <string>
+ If you want to specify a passphrase for the secret key,
+ enter it here. Default is not to use any passphrase.
+ Name-Real: <string>
+ Name-Comment: <string>
+ Name-Email: <string>
+ The 3 parts of a key. Remember to use UTF-8 here.
+ If you don't give any of them, no user ID is created.
+ Expire-Date: <iso-date>|(<number>[d|w|m|y])
+ Set the expiration date for the key (and the subkey). It
+ may either be entered in ISO date format (2000-08-15) or as
+ number of days, weeks, month or years. Without a letter days
+ are assumed.
+
+Here is an example:
+$ cat >foo <<EOF
+ %echo Generating a standard key
+ Key-Type: DSA
+ Key-Length: 1024
+ Subkey-Type: ELG-E
+ Subkey-Length: 1024
+ Name-Real: Joe Tester
+ Name-Comment: with stupid passphrase
+ Name-Email: [email protected]
+ Expire-Date: 0
+ Passphrase: abc
+ %pubring foo.pub
+ %secring foo.sec
+ # Do a commit here, so that we can later print "done" :-)
+ %commit
+ %echo done
+EOF
+$ gpg --batch --gen-key -a foo
+ [...]
+$ gpg --no-default-keyring --secret-keyring foo.sec \
+ --keyring foo.pub --list-secret-keys
+/home/wk/work/gnupg-stable/scratch/foo.sec
+------------------------------------------
+sec 1024D/915A878D 2000-03-09 Joe Tester (with stupid passphrase) <[email protected]>
+ssb 1024g/8F70E2C0 2000-03-09
+
+
Layout of the TrustDB
=====================
diff --git a/doc/HACKING b/doc/HACKING
index 6f4c9ffd8..2f4de27d3 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -10,12 +10,12 @@ CVS Access
==========
Anonymous read-only CVS access is available:
- cvs -z6 -d :pserver:[email protected]:/home/koch/cvs login
+ cvs -z6 -d :pserver:[email protected]:/home/koch/cvs login
use the password "anonymous". To check out the the complete
archive use:
- cvs -z6 -d :pserver:[email protected]:/home/koch/cvs checkout gnupg
+ cvs -z6 -d :pserver:[email protected]:/home/koch/cvs checkout gnupg
This service is provided to help you in hunting bugs and not to deliver
stable snapshots; it may happen that it even does not compile, so please
diff --git a/doc/gpg.sgml b/doc/gpg.sgml
index c20bfb173..51a0f28b3 100644
--- a/doc/gpg.sgml
+++ b/doc/gpg.sgml
@@ -235,8 +235,13 @@ useful for debugging.
<varlistentry>
<term>--gen-key</term>
<listitem><para>
-Generate a new key pair. This command can only be
-used interactive.
+Generate a new key pair. This command is normally only used
+interactive.
+</para>
+<para>
+There is an experimental feature which allows to create keys
+in batch mode. See the file <filename>doc/DETAILS</filename>
+in the source distribution on how to use this.
</para></listitem></varlistentry>
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 3b21ace0c..c8d90540f 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,11 @@
+2000-03-09 12:53:09 Werner Koch ([email protected])
+
+ * keygen.c (ask_expire_interval): Movede parsig to ...
+ (parse_expire_string): ... this new function. And some new control
+ commands.
+ (proc_parameter_file): Add expire date parsing.
+ (do_generate_keypair): Allow the use of specified output files.
+
2000-03-08 10:38:38 Werner Koch ([email protected])
* keygen.c (ask_algo): Removed is_v4 return value and the commented
diff --git a/g10/export.c b/g10/export.c
index 106caa7d7..be72e89d8 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -201,7 +201,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
/* we don't want to export the secret parts of the
- * primary key, this is doen by using GNU protection mode 1001
+ * primary key, this is done by using GNU protection mode 1001
*/
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
diff --git a/g10/g10.c b/g10/g10.c
index 38cd4bbec..f5eb0dd14 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,5 +1,5 @@
/* g10.c - The GnuPG utility (main for gpg)
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
diff --git a/g10/keygen.c b/g10/keygen.c
index 2ed5a70e4..ead51cbc2 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1,5 +1,5 @@
/* keygen.c - generate a key pair
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -59,12 +59,33 @@ struct para_data_s {
union {
DEK *dek;
STRING2KEY *s2k;
+ u32 expire;
char value[1];
} u;
};
+struct output_control_s {
+ int lnr;
+ int dryrun;
+ int use_files;
+ struct {
+ char *fname;
+ char *newfname;
+ IOBUF stream;
+ armor_filter_context_t afx;
+ } pub;
+ struct {
+ char *fname;
+ char *newfname;
+ IOBUF stream;
+ armor_filter_context_t afx;
+ } sec;
+};
+
-static void do_generate_keypair( struct para_data_s *para );
+static void do_generate_keypair( struct para_data_s *para,
+ struct output_control_s *outctrl );
+static int write_keyblock( IOBUF out, KBNODE node );
static void
@@ -537,6 +558,41 @@ ask_keysize( int algo )
}
+/****************
+ * Parse an expire string and return it's value in days.
+ * Returns -1 on error.
+ */
+static int
+parse_expire_string( const char *string )
+{
+ int mult;
+ u32 abs_date=0;
+ u32 curtime = make_timestamp();
+ int valid_days;
+
+ if( !*string )
+ valid_days = 0;
+ else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) {
+ /* This calculation is not perfectly okay because we
+ * are later going to simply multiply by 86400 and don't
+ * correct for leapseconds. A solution would be to change
+ * the whole implemenation to work with dates and not intervals
+ * which are required for v3 keys.
+ */
+ valid_days = abs_date/86400-curtime/86400+1;
+ }
+ else if( (mult=check_valid_days(string)) ) {
+ valid_days = atoi(string) * mult;
+ if( valid_days < 0 || valid_days > 39447 )
+ valid_days = 0;
+ }
+ else {
+ valid_days = -1;
+ }
+ return valid_days;
+}
+
+
static u32
ask_expire_interval(void)
{
@@ -556,32 +612,14 @@ ask_expire_interval(void)
answer = NULL;
for(;;) {
- int mult;
- u32 abs_date=0;
- u32 curtime=0;;
+ u32 curtime=make_timestamp();
m_free(answer);
answer = cpr_get("keygen.valid",_("Key is valid for? (0) "));
cpr_kill_prompt();
trim_spaces(answer);
- curtime = make_timestamp();
- if( !*answer )
- valid_days = 0;
- else if( (abs_date = scan_isodatestr(answer)) && abs_date > curtime ) {
- /* This calculation is not perfectly okay because we
- * are later going to simply multiply by 86400 and don't
- * correct for leapseconds. A solution would be to change
- * the whole implemenation to work with dates and not intervals
- * which are required for v3 keys.
- */
- valid_days = abs_date/86400-curtime/86400+1;
- }
- else if( (mult=check_valid_days(answer)) ) {
- valid_days = atoi(answer) * mult;
- if( valid_days < 0 || valid_days > 39447 )
- valid_days = 0;
- }
- else {
+ valid_days = parse_expire_string( answer );
+ if( valid_days < 0 ) {
tty_printf(_("invalid value\n"));
continue;
}
@@ -924,6 +962,9 @@ get_parameter_u32( struct para_data_s *para, enum para_name key )
if( !r )
return 0;
+ if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE )
+ return r->u.expire;
+
return (unsigned int)strtoul( r->u.value, NULL, 10 );
}
@@ -949,7 +990,8 @@ get_parameter_s2k( struct para_data_s *para, enum para_name key )
static int
-proc_parameter_file( struct para_data_s *para, const char *fname )
+proc_parameter_file( struct para_data_s *para, const char *fname,
+ struct output_control_s *outctrl )
{
struct para_data_s *r;
const char *s1, *s2, *s3;
@@ -994,6 +1036,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname )
}
}
+ /* make DEK and S2K from the Passphrase */
r = get_parameter( para, pPASSPHRASE );
if( r && *r->u.value ) {
/* we have a plain text passphrase - create a DEK from it.
@@ -1022,7 +1065,31 @@ proc_parameter_file( struct para_data_s *para, const char *fname )
r->next = para;
para = r;
}
- do_generate_keypair( para );
+
+ /* make KEYEXPIRE from Expire-Date */
+ r = get_parameter( para, pEXPIREDATE );
+ if( r && *r->u.value ) {
+ i = parse_expire_string( r->u.value );
+ if( i < 0 ) {
+ log_error("%s:%d: invalid expire date\n", fname, r->lnr );
+ return -1;
+ }
+ r->u.expire = i * 86400L;
+ r->key = pKEYEXPIRE; /* change hat entry */
+ /* also set it for the subkey */
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pSUBKEYEXPIRE;
+ r->u.expire = i * 86400L;
+ r->next = para;
+ para = r;
+ }
+
+ if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) {
+ log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr );
+ return -1;
+ }
+
+ do_generate_keypair( para, outctrl );
return 0;
}
@@ -1055,6 +1122,9 @@ read_parameter_file( const char *fname )
const char *err = NULL;
struct para_data_s *para, *r;
int i;
+ struct output_control_s outctrl;
+
+ memset( &outctrl, 0, sizeof( outctrl ) );
if( !fname || !*fname || !strcmp(fname,"-") ) {
fp = stdin;
@@ -1085,8 +1155,46 @@ read_parameter_file( const char *fname )
continue;
keyword = p;
if( *keyword == '%' ) {
- /* for now these are all comments but in future they may be used
- * to control certain aspects */
+ for( ; !isspace(*p); p++ )
+ ;
+ if( *p )
+ *p++ = 0;
+ for( ; isspace(*p); p++ )
+ ;
+ value = p;
+ trim_trailing_ws( value, strlen(value) );
+ if( !stricmp( keyword, "%echo" ) )
+ log_info("%s\n", value );
+ else if( !stricmp( keyword, "%dry-run" ) )
+ outctrl.dryrun = 1;
+ else if( !stricmp( keyword, "%commit" ) ) {
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
+ release_parameter_list( para );
+ para = NULL;
+ }
+ else if( !stricmp( keyword, "%pubring" ) ) {
+ if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) )
+ ; /* still the same file - ignore it */
+ else {
+ m_free( outctrl.pub.newfname );
+ outctrl.pub.newfname = m_strdup( value );
+ outctrl.use_files = 1;
+ }
+ }
+ else if( !stricmp( keyword, "%secring" ) ) {
+ if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) )
+ ; /* still the same file - ignore it */
+ else {
+ m_free( outctrl.sec.newfname );
+ outctrl.sec.newfname = m_strdup( value );
+ outctrl.use_files = 1;
+ }
+ }
+ else
+ log_info("skipping control `%s' (%s)\n", keyword, value );
+
+
continue;
}
@@ -1095,7 +1203,8 @@ read_parameter_file( const char *fname )
err = "missing colon";
break;
}
- *p++ = 0;
+ if( *p )
+ *p++ = 0;
for( ; isspace(*p); p++ )
;
if( !*p ) {
@@ -1119,7 +1228,8 @@ read_parameter_file( const char *fname )
}
if( keywords[i].key == pKEYTYPE && para ) {
- proc_parameter_file( para, fname );
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
release_parameter_list( para );
para = NULL;
}
@@ -1146,8 +1256,19 @@ read_parameter_file( const char *fname )
log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) );
}
else if( para ) {
- proc_parameter_file( para, fname );
+ outctrl.lnr = lnr;
+ proc_parameter_file( para, fname, &outctrl );
}
+
+ if( outctrl.use_files ) { /* close open streams */
+ iobuf_close( outctrl.pub.stream );
+ iobuf_close( outctrl.sec.stream );
+ m_free( outctrl.pub.fname );
+ m_free( outctrl.pub.newfname );
+ m_free( outctrl.sec.fname );
+ m_free( outctrl.sec.newfname );
+ }
+
release_parameter_list( para );
if( strcmp( fname, "-" ) )
fclose(fp);
@@ -1170,6 +1291,9 @@ generate_keypair( const char *fname )
u32 expire;
struct para_data_s *para = NULL;
struct para_data_s *r;
+ struct output_control_s outctrl;
+
+ memset( &outctrl, 0, sizeof( outctrl ) );
if( opt.batch ) {
read_parameter_file( fname );
@@ -1216,16 +1340,14 @@ generate_keypair( const char *fname )
expire = ask_expire_interval();
r = m_alloc_clear( sizeof *r + 20 );
r->key = pKEYEXPIRE;
- sprintf( r->u.value, "%lu", (ulong)expire );
+ r->u.expire = expire;
+ r->next = para;
+ para = r;
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pSUBKEYEXPIRE;
+ r->u.expire = expire;
r->next = para;
para = r;
- if( both ) {
- r = m_alloc_clear( sizeof *r + 20 );
- r->key = pSUBKEYEXPIRE;
- sprintf( r->u.value, "%lu", (ulong)expire );
- r->next = para;
- para = r;
- }
uid = ask_user_id(0);
if( !uid ) {
@@ -1253,13 +1375,14 @@ generate_keypair( const char *fname )
para = r;
}
- proc_parameter_file( para, "[internal]" );
+ proc_parameter_file( para, "[internal]", &outctrl );
release_parameter_list( para );
}
static void
-do_generate_keypair( struct para_data_s *para )
+do_generate_keypair( struct para_data_s *para,
+ struct output_control_s *outctrl )
{
char *pub_fname = NULL;
char *sec_fname = NULL;
@@ -1269,12 +1392,68 @@ do_generate_keypair( struct para_data_s *para )
const char *s;
int rc;
- /* check whether we are allowed to write to the keyrings */
- pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
- sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
+ if( outctrl->dryrun ) {
+ log_info("dry-run mode - key generation skipped\n");
+ return;
+ }
+
+
+ if( outctrl->use_files ) {
+ if( outctrl->pub.newfname ) {
+ iobuf_close(outctrl->pub.stream);
+ outctrl->pub.stream = NULL;
+ m_free( outctrl->pub.fname );
+ outctrl->pub.fname = outctrl->pub.newfname;
+ outctrl->pub.newfname = NULL;
+
+ outctrl->pub.stream = iobuf_create( outctrl->pub.fname );
+ if( !outctrl->pub.stream ) {
+ log_error("can't create `%s': %s\n", outctrl->pub.newfname,
+ strerror(errno) );
+ return;
+ }
+ if( opt.armor ) {
+ outctrl->pub.afx.what = 1;
+ iobuf_push_filter( outctrl->pub.stream, armor_filter,
+ &outctrl->pub.afx );
+ }
+ }
+ if( outctrl->sec.newfname ) {
+ iobuf_close(outctrl->sec.stream);
+ outctrl->sec.stream = NULL;
+ m_free( outctrl->sec.fname );
+ outctrl->sec.fname = outctrl->sec.newfname;
+ outctrl->sec.newfname = NULL;
+
+ outctrl->sec.stream = iobuf_create( outctrl->sec.fname );
+ if( !outctrl->sec.stream ) {
+ log_error("can't create `%s': %s\n", outctrl->sec.newfname,
+ strerror(errno) );
+ return;
+ }
+ if( opt.armor ) {
+ outctrl->sec.afx.what = 5;
+ iobuf_push_filter( outctrl->sec.stream, armor_filter,
+ &outctrl->sec.afx );
+ }
+ }
+ pub_fname = outctrl->pub.fname; /* only for info output */
+ sec_fname = outctrl->sec.fname; /* only for info output */
+ assert( outctrl->pub.stream );
+ assert( outctrl->sec.stream );
+ }
+ else {
+ /* check whether we are allowed to write to the keyrings */
+ /* It is probably wrong to use the default names here
+ * but becuase I never gpt any complaints, we better leave
+ * it as it is. */
+ pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
+ sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
+ }
+
if( opt.verbose ) {
- log_info(_("writing public certificate to `%s'\n"), pub_fname );
- log_info(_("writing secret certificate to `%s'\n"), sec_fname );
+ log_info(_("writing public key to `%s'\n"), pub_fname );
+ log_info(_("writing secret key to `%s'\n"), sec_fname );
}
/* we create the packets as a tree of kbnodes. Because the structure
@@ -1317,7 +1496,18 @@ do_generate_keypair( struct para_data_s *para )
}
- if( !rc ) {
+ if( !rc && outctrl->use_files ) { /* direct write to specified files */
+ rc = write_keyblock( outctrl->pub.stream, pub_root );
+ if( rc )
+ log_error("can't write public key: %s\n", g10_errstr(rc) );
+ if( !rc ) {
+ rc = write_keyblock( outctrl->sec.stream, sec_root );
+ if( rc )
+ log_error("can't write secret key: %s\n", g10_errstr(rc) );
+ }
+
+ }
+ else if( !rc ) { /* write to the standard keyrings */
KBPOS pub_kbpos;
KBPOS sec_kbpos;
int rc1 = -1;
@@ -1377,10 +1567,9 @@ do_generate_keypair( struct para_data_s *para )
unlock_keyblock( &sec_kbpos );
}
-
if( rc ) {
if( opt.batch )
- log_error(_("Key generation failed: %s\n"), g10_errstr(rc) );
+ log_error("key generation failed: %s\n", g10_errstr(rc) );
else
tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
}
@@ -1388,8 +1577,10 @@ do_generate_keypair( struct para_data_s *para )
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
- m_free(pub_fname);
- m_free(sec_fname);
+ if( !outctrl->use_files ) {
+ m_free(pub_fname);
+ m_free(sec_fname);
+ }
}
@@ -1491,3 +1682,20 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
return okay;
}
+/****************
+ * Write a keyblock to an output stream
+ */
+static int
+write_keyblock( IOBUF out, KBNODE node )
+{
+ for( ; node ; node = node->next ) {
+ int rc = build_packet( out, node->pkt );
+ if( rc ) {
+ log_error("build_packet(%d) failed: %s\n",
+ node->pkt->pkttype, g10_errstr(rc) );
+ return G10ERR_WRITE_FILE;
+ }
+ }
+ return 0;
+}
+
diff --git a/util/ChangeLog b/util/ChangeLog
index 4fdc43f7e..4106b075d 100644
--- a/util/ChangeLog
+++ b/util/ChangeLog
@@ -1,3 +1,7 @@
+2000-03-09 14:04:22 Werner Koch ([email protected])
+
+ * argparse.c (default_strusage): Changed year of default copyright.
+
Tue Mar 7 18:45:31 CET 2000 Werner Koch <[email protected]>
* secmem.c (lock_pool): No more warning for QNX. By Sam Roberts.
diff --git a/util/argparse.c b/util/argparse.c
index c6f405f62..929d62a79 100644
--- a/util/argparse.c
+++ b/util/argparse.c
@@ -892,7 +892,7 @@ default_strusage( int level )
switch( level ) {
case 11: p = "foo"; break;
case 13: p = "0.0"; break;
- case 14: p = "Copyright (C) 1999 Free Software Foundation, Inc."; break;
+ case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break;
case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"