See ChangeLog ;-). Key validation should now be faster
authorWerner Koch <wk@gnupg.org>
Fri, 13 Nov 1998 19:41:41 +0000 (19:41 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 13 Nov 1998 19:41:41 +0000 (19:41 +0000)
23 files changed:
ABOUT-NLS
README
TODO
doc/DETAILS
doc/HACKING
doc/OpenPGP
doc/gpg.1pod
g10/ChangeLog
g10/g10.c
g10/keylist.c
g10/mainproc.c
g10/options.h
g10/options.skel
g10/pkclist.c
g10/ringedit.c
g10/tdbio.c
g10/tdbio.h
g10/trustdb.c
g10/trustdb.h
include/util.h
util/argparse.c
util/dotlock.c
util/strgutil.c

index 249a4b5..28d38c7 100644 (file)
--- a/ABOUT-NLS
+++ b/ABOUT-NLS
@@ -137,7 +137,8 @@ Each translation team has its own mailing list, courtesy of Linux
 International.  You may reach your translation team at the address
 `LL@li.org', replacing LL by the two-letter ISO 639 code for your
 language.  Language codes are *not* the same as the country codes given
-in ISO 3166.  The following translation teams exist, as of August 1998:
+in ISO 3166.  The following translation teams exist, as of December
+1997:
 
      Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
      Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
@@ -172,79 +173,42 @@ Available Packages
 ==================
 
    Languages are not equally supported in all packages.  The following
-matrix shows the current state of internationalization, as of August
-1998.  The matrix shows, in regard of each package, for which languages
+matrix shows the current state of internationalization, as of December
+1997.  The matrix shows, in regard of each package, for which languages
 PO files have been submitted to translation coordination.
 
-     Ready PO files    cs da de el en es fi fr it
-                     .----------------------------.
-     bash            |       []             []    |
-     bison           |       []             []    |
-     clisp           |       []    [] []    []    |
-     cpio            |       []       []    []    |
-     diffutils       |       []       []    []    |
-     enscript        |       []       [] [] []    |
-     fileutils       | []    []       []    []    |
-     findutils       |       []       []    [] [] |
-     flex            |                []    []    |
-     gcal            |       []             []    |
-     gettext         |    [] [] []    []    []    |
-     grep            |       [] []    []    []    |
-     hello           |    [] []       []    [] [] |
-     id-utils        |       []             []    |
-     indent          |    [] []                   |
-     libc            |       []       []    []    |
-     m4              |       []             []    |
-     make            |       []       []    []    |
-     music           |                      []    |
-     ptx             |       []       []    []    |
-     recode          |    [] []       []    []    |
-     sed             |                            |
-     sh-utils        |       []       []    []    |
-     sharutils       | []    [] []    []    []    |
-     tar             | []    []             [] [] |
-     texinfo         | []    []             []    |
-     textutils       | []    []       []    []    |
-     wdiff           | []    []       []    []    |
-     wget            | []    [] []             [] |
-                     `----------------------------'
-                       cs da de el en es fi fr it
-                        7  4 26  4  1 18  1 26  4
-     
-                       ja ko nl no pl pt ru sl sv
-                     .----------------------------.
-     bash            |       []                   |  3
-     bison           |       []                   |  3
-     clisp           |                            |  4
-     cpio            |    [] []    []             |  6
-     diffutils       |             []          [] |  5
-     enscript        |       []             []    |  6
-     fileutils       |    [] []    [] [] [] [] [] | 11
-     findutils       |    [] []    []    []    [] |  9
-     flex            |    []                   [] |  4
-     gcal            |       []    []          [] |  5
-     gettext         |    [] [] [] [] []    [] [] | 13
-     grep            |    [] [] [] []    [] [] [] | 11
-     hello           |    [] [] [] [] []    [] [] | 12
-     id-utils        |             []             |  3
-     indent          |    []       []    []       |  5
-     libc            |    [] [] [] []          [] |  8
-     m4              | []    []          []    [] |  6
-     make            |    [] []    []             |  6
-     music           |             []             |  2
-     ptx             |       [] [] [] []       [] |  8
-     recode          |       []    [] []    [] [] |  9
-     sed             |                            |  0
-     sh-utils        |       [] [] [] []       [] |  8
-     sharutils       |       []                [] |  7
-     tar             |    [] [] [] [] []    [] [] | 11
-     texinfo         |       []                   |  4
-     textutils       |    [] [] [] []          [] |  9
-     wdiff           |       [] [] []          [] |  8
-     wget            |          []                |  5
-                     `----------------------------'
-       18 teams        ja ko nl no pl pt ru sl sv
-       29 domains       1 12 21 11 19  7  5  7 17  191
+     Ready PO files    cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+                     .----------------------------------------------------.
+     bash            |       []          []          []                   |  3
+     bison           |       []          []          []                   |  3
+     clisp           |       [] [] []    []                               |  4
+     cpio            |       []    []    []       [] []    []             |  6
+     diffutils       |       []    []    []                []          [] |  5
+     enscript        |       []    [] [] []          []             []    |  6
+     fileutils       | []    []    []    []       [] []    [] []    [] [] | 10
+     findutils       |       []    []    [] []    [] []    []    []    [] |  9
+     flex            |             []    []       []                   [] |  4
+     gcal            |       []          []          []    []          [] |  5
+     gettext         |    [] []    []    []       [] [] [] [] []    [] [] | 12
+     grep            |       []    []    []       [] [] [] []    [] [] [] | 10
+     hello           |    [] []    []    []       [] [] [] [] []    [] [] | 11
+     id-utils        |       []          []                []             |  3
+     indent          |    [] []                   []       []    []       |  5
+     libc            |       []    []    []       [] []    []          [] |  7
+     m4              |       []          []    []    []          []    [] |  6
+     make            |       []    []    []       [] []    []             |  6
+     music           |                   []                []             |  2
+     ptx             |       []    []    []          [] [] [] []       [] |  8
+     recode          |    [] []    []    []          []    [] []    [] [] |  9
+     sh-utils        |       []    []    []          [] [] [] []       [] |  8
+     sharutils       | []    []    []    []          []                [] |  6
+     tar             | []    []          [] []    [] [] [] [] []    [] [] | 11
+     texinfo         | []    []          []                               |  3
+     textutils       | []    []    []    []       [] [] [] []          [] |  9
+     wdiff           | []    []    []    []          [] [] []          [] |  8
+                     `----------------------------------------------------'
+       17 languages    cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+       27 packages      6  4 25  1 18  1 26  2  1 12 20  9 19  7  4  7 17  179
 
    Some counters in the preceding matrix are higher than the number of
 visible blocks let us expect.  This is because a few extra PO files are
@@ -257,23 +221,6 @@ distributed as such by its maintainer.  There might be an observable
 lag between the mere existence a PO file and its wide availability in a
 distribution.
 
-   If August 1998 seems to be old, you may fetch a more recent copy of
-this `ABOUT-NLS' file on most GNU archive sites.
-
-Using `gettext' in new packages
-===============================
-
-   If you are writing a freely available program and want to
-internationalize it you are welcome to use GNU `gettext' in your
-package.  Of course the GNU Public License applies to your sources from
-then if you include `gettext' directly in your distribution on but
-since you are writing free software anyway this is no restriction.
-
-   Once the sources are change appropriately and the setup can handle to
-use of `gettext' the only thing missing are the translations.  The Free
-Translation Project is also available for packages which are not
-developed inside the GNU project.  Therefore the information given above
-applies also for every other Free Software Project.  Contact
-`translation@iro.umontreal.ca' to make the `.pot' files available to
-the translation teams.
+   If December 1997 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites.
 
diff --git a/README b/README
index f25ff6f..513495a 100644 (file)
--- a/README
+++ b/README
@@ -43,8 +43,8 @@
     IDEA (which is patented worldwide) and RSA (which is patented in
     the United States until Sep 20, 2000).
 
-    GnuPG is in almost all  aspects compatible with other OpenPGP
-    implementations.
+    GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
+    deatils.
 
     The default algorithms are now DSA and ELGamal.  ELGamal for signing
     is still available, but due to the larger size of such signatures it
diff --git a/TODO b/TODO
index b0b835a..bb237e6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,12 @@
 
-    * Update the keyring on ftp.ggug.de
+    * I noticed, that we sometimes have only 3 items in atrustrecord, but
+      a next pointer ro more records - check wehther the reuse code really
+      works. Maybe this is the reason for the "Hmmm puiblic key lost"
+
+    * Update the keyring at ftp.ggug.de
+
+    * expire date is not shown in --edit-key for subkeys.
+      and prefs are not correctly listed for some keys???? (Brian)
 
     * support for mpi/powerpc  split is still combined or whatever
 
@@ -84,6 +91,5 @@
 
     * Add some stuff for DU cc
 
-    * use "passphrase" instead of "pass phrase"
     * Use "user ID", "trustdb" and "WARNING".
 
index 0ac48bd..e3c4994 100644 (file)
@@ -14,6 +14,8 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
            fpr = fingerprint: (fingerprint is in field 10)
 
  2. Field:  A letter describing the calculated trust, see doc/FAQ
+           This is a single letter, but be prepared that additional
+           information may follow in some future versions.
            (not used for secret keys)
  3. Field:  length of key in bits.
  4. Field:  Algorithm: 1 = RSA
@@ -30,6 +32,8 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
            because keyids may not be unique - a program may use this
            number to access keys later.
  9. Field:  Ownertrust (primary public keys only)
+           This is a single letter, but be prepared that additional
+           information may follow in some future versions.
 10. Field:  User-ID.  The value is quoted like a C string to avoid
            control characters (the colon is quoted "\x3a").
 
@@ -83,7 +87,11 @@ Record type 1:
      1 byte value 2
      3 bytes 'gpg'  magic value
      1 byte Version of the TrustDB
-     3 byte reserved
+     1 byte marginals needed
+     1 byte completes needed
+     1 byte max_cert_depth
+           The three items are used to check whether the cached
+           validity value from the dir record can be used.
      1 u32  locked flags
      1 u32  timestamp of trustdb creation
      1 u32  timestamp of last modification
@@ -110,8 +118,9 @@ Record type 2: (directory record)
      1 u32   List of uid-records
      1 u32   cache record
      1 byte  ownertrust
-     1 byte  sigflag
-    20 byte reserved
+     1 byte  dirflag
+     1 byte  validity
+    19 byte reserved
 
 
 Record type 3: (key record)
index f309284..e4c1aa9 100644 (file)
@@ -10,12 +10,12 @@ CVS Access
 ==========
 Anonymous read-only CVS access is available:
 
-  cvs -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
+  cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
 
 use the password "anonymous".  To check out the the complete
 archive use:
 
-  cvs -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs checkout gnupg
+  cvs -z6 -d :pserver:anonymous@ftp.guug.de:/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
@@ -51,6 +51,7 @@ RFCs
 
 2279  UTF-8, a transformation format of ISO 10646.
 
+2440  OpenPGP.
 
 
 
index 647d891..62f9cba 100644 (file)
@@ -1,28 +1,15 @@
                    GnuPG and OpenPGP
                    =================
 
-   The current OpenPGP draft expires 1999-02.
+   See RFC2440 for a description of OpenPGP.
 
-   OpenPGP is an Internet-Draft.  Internet-Drafts are working
-   documents of the Internet Engineering Task Force (IETF), its areas,
-   and its working groups.  Note that other groups may also distribute
-   working documents as Internet-Drafts.
-
-   Internet-Drafts are draft documents valid for a maximum of six
-   months and may be updated, replaced, or obsoleted by other documents
-   at any time.  It is inappropriate to use Internet-Drafts as
-   reference material or to cite them other than as "work in progress."
-
-   To view the entire list of current Internet-Drafts, please check the
-   "1id-abstracts.txt" listing contained in the Internet-Drafts Shadow
-   Directories on ftp.is.co.za (Africa), ftp.nordu.net (Northern
-   Europe), ftp.nis.garr.it (Southern Europe), munnari.oz.au (Pacific
-   Rim), ftp.ietf.org (US East Coast), or ftp.isi.edu (US West Coast).
 
 
   Compatibility Notes
   ===================
-   GnuPG (>=0.4.1) is in compliance with OpenPGP despite these exeptions:
+   GnuPG (>=0.4.1) is in compliance with RFC2440 despite these exeptions:
+
+    ===> Please can someone check this <=========
 
     * (5.1) The critical bit in signature subpackets is currently
       ignored. This will be fixed soon.
index aacefcb..e299b38 100644 (file)
@@ -345,6 +345,9 @@ B<--marginals-needed> I<n>
     Number of marginally trusted users to introduce a new
     key signator (defaults to 3)
 
+B<--max-cert-depth> I<n>
+    Maximum depth of a certification chain (default is 5).
+
 B<--cipher-algo> I<name>
     Use I<name> as cipher algorithm. Running the program
     with the command B<--version> yields a list of supported
index af6daf0..1f072a9 100644 (file)
@@ -1,3 +1,25 @@
+Fri Nov 13 07:39:58 1998  Werner Koch  <werner.koch@guug.de>
+
+       * trustdb.c (collect_paths): Removed a warning message.
+       (enum_trust_web): Removed.
+       (enum_cert_paths): New.
+       * pkclist.c (add_ownertrust): Changed to use enum_cert_paths.
+       (edit_ownertrust): Now list ceritficates on request.
+       (show_paths): New.
+
+Wed Nov 11 18:05:44 1998  Werner Koch  <werner.koch@guug.de>
+
+       * g10.c (main): New option --max-cert-depth
+       * tdbio.h: add new fields to ver and dir record.
+       * tdbio.c: read/write/dump of these fields.
+       (tdbio_db_matches_options): New.
+       * trustdb.c: replaced MAC_CERT_DEPTH by opt.max_cert_depth.
+       (do_check): cache validity and changed other functions
+       to reset the cached value.
+
+       * keylist.c (list_one): Now lists the ownertrust.
+       * mainproc.c (list_node): Ditto.
+
 Tue Nov 10 10:08:59 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * g10.c (g10_exit): Now looks at the new g10_errors_seen.
index 7deb3da..86dd901 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -114,6 +114,7 @@ enum cmd_and_opt_values { aNull = 0,
     oNoComment,
     oCompletesNeeded,
     oMarginalsNeeded,
+    oMaxCertDepth,
     oLoadExtension,
     oRFC1991,
     oCipherAlgo,
@@ -230,6 +231,7 @@ static ARGPARSE_OPTS opts[] = {
     { oNoComment, "no-comment", 0,   N_("do not write comment packets")},
     { oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
     { oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
+    { oMaxCertDepth,   "max-cert-depth", 1, "@" },
     { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
     { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
@@ -533,6 +535,7 @@ main( int argc, char **argv )
     opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
+    opt.max_cert_depth = 5;
     opt.homedir = getenv("GNUPGHOME");
     if( !opt.homedir || !*opt.homedir ) {
       #ifdef __MINGW32__
@@ -699,6 +702,7 @@ main( int argc, char **argv )
          case oNoComment: opt.no_comment=1; break;
          case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
          case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
+         case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
          case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
          case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
          case oNoOptions: break; /* no-options */
@@ -819,6 +823,8 @@ main( int argc, char **argv )
        log_error(_("completes-needed must be greater than 0\n"));
     if( opt.marginals_needed < 2 )
        log_error(_("marginals-needed must be greater than 1\n"));
+    if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 )
+       log_error(_("max-cert-depth must be in range 1 to 255\n"));
     switch( opt.s2k_mode ) {
       case 0:
        log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));
index 257e869..f2ded04 100644 (file)
@@ -207,7 +207,8 @@ list_keyblock( KBNODE keyblock, int secret )
            if( pk->local_id )
                printf("%lu", pk->local_id );
            putchar(':');
-           /* fixme: add ownertrust here */
+           if( pk->local_id )
+               putchar( get_ownertrust_info( pk->local_id ) );
            putchar(':');
        }
        else
index c857874..c21516d 100644 (file)
@@ -483,7 +483,8 @@ list_node( CTX c, KBNODE node )
            if( c->local_id )
                printf("%lu", c->local_id );
            putchar(':');
-           /* fixme: add ownertrust here */
+           if( c->local_id )
+               putchar( get_ownertrust_info( c->local_id ) );
            putchar(':');
        }
        else
index 0ad4651..1502d74 100644 (file)
@@ -49,6 +49,7 @@ struct {
     int no_comment;
     int marginals_needed;
     int completes_needed;
+    int max_cert_depth;
     const char *homedir;
     int skip_verify;
     int compress_keys;
index 1d7ebd7..3ce6e5a 100644 (file)
@@ -41,3 +41,8 @@ compress-algo 1
 #charset koi8-r
 
 
+# You may define aliases like this:
+#   alias mynames  -u 0x12345678 -u 0x456789ab -z 9
+# everytime you use --mynames, it will be expanded to the options
+# in the above defintion.  The name of the alias may not be abbreviated.
+
index 2f39287..f56708c 100644 (file)
 #define CONTROL_D ('D' - 'A' + 1)
 
 
+static void
+show_paths( ulong lid )
+{
+    void *context = NULL;
+    unsigned otrust, validity;
+    int level;
+
+    while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){
+       char *p;
+       int rc;
+       size_t n;
+       u32 keyid[2];
+       PKT_public_key *pk ;
+
+       rc = keyid_from_lid( lid, keyid );
+       if( rc ) {
+           log_error("ooops: can't get keyid for lid %lu\n", lid);
+           return;
+       }
+
+       pk = m_alloc_clear( sizeof *pk );
+       rc = get_pubkey( pk, keyid );
+       if( rc ) {
+           log_error("key %08lX: public key not found: %s\n",
+                                   (ulong)keyid[1], g10_errstr(rc) );
+           return;
+       }
+
+       tty_printf("%*s%4u%c/%08lX.%lu %s \"",
+                 level*2,
+                 nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
+                 (ulong)keyid[1], lid, datestr_from_pk( pk ) );
+       p = get_user_id( keyid, &n );
+       tty_print_string( p, n ),
+       m_free(p);
+       tty_printf("\"\n\n");
+    }
+    enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
+}
+
+
+
+
 /****************
  * Returns true if an ownertrust has changed.
  */
@@ -68,7 +111,7 @@ edit_ownertrust( ulong lid, int mode )
     }
 
     if( !mode ) {
-       tty_printf(_("No owner trust defined for %lu:\n"
+       tty_printf(_("No trust value assigned to %lu:\n"
                   "%4u%c/%08lX %s \""), lid,
                  nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
                  (ulong)keyid[1], datestr_from_pk( pk ) );
@@ -115,7 +158,9 @@ edit_ownertrust( ulong lid, int mode )
            break;
        }
        else if( *p == ans[0] || *p == ans[1] ) {
-           tty_printf(_("You will see a list of signators etc. here\n"));
+           tty_printf(_(
+               "Certificates leading to an ultimately trusted key:\n"));
+           show_paths( lid );
        }
        else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
            break ; /* back to the menu */
@@ -138,8 +183,8 @@ add_ownertrust( PKT_public_key *pk )
     int rc;
     void *context = NULL;
     ulong lid;
-    unsigned trust;
-    int any=0;
+    unsigned otrust, validity;
+    int any=0, changed=0, any_undefined=0;
 
     tty_printf(
 _("Could not find a valid trust path to the key.  Let's see whether we\n"
@@ -152,22 +197,25 @@ _("Could not find a valid trust path to the key.  Let's see whether we\n"
     }
 
     lid = pk->local_id;
-    while( !(rc=enum_trust_web( &context, &lid )) ) {
-       trust = get_ownertrust( lid );
-       if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
-           trust == TRUST_UNKNOWN ) {
+    while( enum_cert_paths( &context, &lid, &otrust, &validity ) != -1 ) {
+       any=1;
+       if( otrust == TRUST_UNDEFINED || otrust == TRUST_EXPIRED ||
+           otrust == TRUST_UNKNOWN ) {
+           any_undefined=1;
            if( edit_ownertrust( lid, 0 ) )
-               any=1;
+               changed=1;
        }
     }
-    if( rc == -1 )
-       rc = 0;
-    enum_trust_web( &context, NULL ); /* close */
+    enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
 
     if( !any )
-       tty_printf(_("No owner trust values changed.\n\n") );
+       tty_printf(_("No path leading to one of our keys found.\n\n") );
+    else if( !any_undefined )
+       tty_printf(_("No certificates with undefined trust found.\n\n") );
+    else if( !changed )
+       tty_printf(_("No trust values changed.\n\n") );
 
-    return rc? rc : any? 0:-1;
+    return any? 0:-1;
 }
 
 /****************
index ebeceb1..d12afa6 100644 (file)
@@ -832,6 +832,127 @@ update_keyblock( KBPOS *kbpos, KBNODE root )
 
 \f
 /****************************************************************
+ ********** Implemenation of a user ID database    **************
+ ****************************************************************/
+#if 0
+/****************
+ * Layout of the user ID db
+ *
+ * This user ID DB provides fast lookup of user ID, but the user ids are
+ * not in any specific order.
+ *
+ * A string "GnuPG user db", a \n.
+ * user ids of one key, delimited by \t,
+ * a # or ^ followed by a 20 byte fingerprint, followed by an \n 
+ * The literal characters =, \n, \t, #, ^ must be replaced by a equal sign
+ * and their hex value.
+ *
+ * (We use Boyer/Moore pattern matching)
+ */
+
+/****************
+ * This compiles pattern to the distance table, the table will be allocate
+ * here and must be freed by using free().
+ * Returns: Ptr to new allocated Table
+ *         Caller must free the table.
+ */
+
+static size_t *
+compile_bm_table( const byte *pattern, size_t len )
+{
+    ushort *dist;
+    int i;
+
+    dist = m_alloc_clear( 256 * sizeof *dist );
+    for(i=0; i < 256; i++ )
+       dist[i] = len;
+    for(i=0; i < len-1; i++ )
+       dTbl[p[i]] = len-i-1;
+    return dist;
+}
+
+
+
+
+/****************
+ * Search BUF of BUFLEN for pattern P of length PATLEN.
+ * dist is the Boyer/Moore distance table of 256 Elements,
+ * case insensitive search is done if IGNCASE is true (In this case
+ * the distance table has to compiled from uppercase chacaters and
+ * PAT must also be uppercase.
+ * Returns: Prt to maching string in BUF, or NULL if not found.
+ */
+
+static const *
+do_bm_search( const byte *buf, size_t buflen,
+             const byte *pat, size_t patlen, size_t *dist, int igncase )
+{
+    int i, j, k;
+
+    if( igncase ) {
+       int c, c1;
+
+       for( i = --patlen; i < buflen; i += dist[c1] )
+           for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
+                                         j--, k--, c=toupper(buf[k]) ) {
+               if( !j )
+                   return buf+k;
+           }
+    }
+    else {
+       for( i = --patlen; i < buflen; i += dist[buf[i]] )
+           for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
+               if( !j )
+                   return buf+k;
+           }
+    }
+    return NULL;
+}
+
+
+typedef struct {
+    size_t dist[256];
+} *SCAN_USER_HANDLE;
+
+static SCAN_USER_HANDLE
+scan_user_file_open( const byte *name )
+{
+    SCAN_USER_HANDLE hd;
+    size_t *dist;
+    int i;
+
+    hd = m_alloc_clear( sizeof *hd );
+    dist = hd->dist;
+    /* compile the distance table */
+    for(i=0; i < 256; i++ )
+       dist[i] = len;
+    for(i=0; i < len-1; i++ )
+       dTbl[p[i]] = len-i-1;
+    /* setup other things */
+
+    return hd;
+}
+
+static int
+scan_user_file_close( SCAN_USER_HANDLE hd )
+{
+    m_free( hd );
+}
+
+static int
+scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
+{
+    char record[1000];
+
+    /* read a record */
+
+
+}
+#endif
+
+
+\f
+/****************************************************************
  ********** Functions which operates on regular keyrings ********
  ****************************************************************/
 
index 11b2dcf..bac8a33 100644 (file)
@@ -419,6 +419,9 @@ tdbio_set_dbname( const char *new_dbname, int create )
            memset( &rec, 0, sizeof rec );
            rec.r.ver.version = 2;
            rec.r.ver.created = make_timestamp();
+           rec.r.ver.marginals =  opt.marginals_needed;
+           rec.r.ver.completes =  opt.completes_needed;
+           rec.r.ver.cert_depth = opt.max_cert_depth;
            rec.rectype = RECTYPE_VER;
            rec.recnum = 0;
            rc = tdbio_write_record( &rec );
@@ -511,6 +514,41 @@ create_hashtable( TRUSTREC *vr, int type )
 }
 
 
+int
+tdbio_db_matches_options()
+{
+    static int yes_no = -1;
+
+    if( yes_no == -1 ) {
+       TRUSTREC vr;
+       int rc;
+
+       rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
+       if( rc )
+           log_fatal( _("%s: error reading version record: %s\n"),
+                                                   db_name, g10_errstr(rc) );
+
+       if( !vr.r.ver.marginals && !vr.r.ver.completes
+                               && !vr.r.ver.cert_depth )
+       {   /* special hack for trustdbs created by old versions of GnuPG */
+           vr.r.ver.marginals =  opt.marginals_needed;
+           vr.r.ver.completes =  opt.completes_needed;
+           vr.r.ver.cert_depth = opt.max_cert_depth;
+           rc = tdbio_write_record( &vr );
+           if( !rc && !in_transaction )
+               rc = tdbio_sync();
+           if( rc )
+               log_error( _("%s: error writing version record: %s\n"),
+                                               db_name, g10_errstr(rc) );
+       }
+
+       yes_no = vr.r.ver.marginals == opt.marginals_needed
+                && vr.r.ver.completes == opt.completes_needed
+                && vr.r.ver.cert_depth == opt.max_cert_depth;
+    }
+    return yes_no;
+}
+
 
 /****************
  * Return the record number of the keyhash tbl or create a new one.
@@ -839,19 +877,24 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
     switch( rec->rectype ) {
       case 0: fprintf(fp, "blank\n");
        break;
-      case RECTYPE_VER: fprintf(fp, "version, kd=%lu, sd=%lu, free=%lu\n",
+      case RECTYPE_VER: fprintf(fp,
+           "version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d\n",
            rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
-                                  rec->r.ver.firstfree );
+                                  rec->r.ver.firstfree,
+                                  rec->r.ver.marginals,
+                                  rec->r.ver.completes,
+                                  rec->r.ver.cert_depth );
        break;
       case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
        break;
       case RECTYPE_DIR:
-       fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
+       fprintf(fp, "dir %lu, keys=%lu, uids=%lu, t=%02x",
                    rec->r.dir.lid,
                    rec->r.dir.keylist,
                    rec->r.dir.uidlist,
-                   rec->r.dir.cacherec,
                    rec->r.dir.ownertrust );
+       if( rec->r.dir.dirflags & DIRF_VALVALID )
+           fprintf( fp, ", v=%02x", rec->r.dir.validity );
        if( rec->r.dir.dirflags & DIRF_CHECKED ) {
            if( rec->r.dir.dirflags & DIRF_VALID )
                fputs(", valid", fp );
@@ -863,7 +906,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
        putc('\n', fp);
        break;
       case RECTYPE_KEY:
-       fprintf(fp, "key %lu, next=%lu, algo=%d, ",
+       fprintf(fp, "key %lu, n=%lu a=%d ",
                   rec->r.key.lid,
                   rec->r.key.next,
                   rec->r.key.pubkey_algo );
@@ -1005,7 +1048,9 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        }
        p += 2; /* skip "pgp" */
        rec->r.ver.version  = *p++;
-       p += 3; /* reserved bytes */
+       rec->r.ver.marginals = *p++;
+       rec->r.ver.completes = *p++;
+       rec->r.ver.cert_depth = *p++;
        p += 4; /* lock flags */
        rec->r.ver.created  = buftoulong(p); p += 4;
        rec->r.ver.modified = buftoulong(p); p += 4;
@@ -1034,6 +1079,18 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        rec->r.dir.cacherec = buftoulong(p); p += 4;
        rec->r.dir.ownertrust = *p++;
        rec->r.dir.dirflags   = *p++;
+       rec->r.dir.validity   = *p++;
+       switch( rec->r.dir.validity ) {
+         case 0:
+         case TRUST_UNDEFINED:
+         case TRUST_NEVER:
+         case TRUST_MARGINAL:
+         case TRUST_FULLY:
+         case TRUST_ULTIMATE:
+           break;
+         default:
+           log_info("lid %lu: invalid validity value - cleared\n", recnum);
+       }
        if( rec->r.dir.lid != recnum ) {
            log_error( "%s: dir LID != recnum (%lu,%lu)\n",
                              db_name, rec->r.dir.lid, (ulong)recnum );
@@ -1137,7 +1194,10 @@ tdbio_write_record( TRUSTREC *rec )
            BUG();
        memcpy(p-1, "gpg", 3 ); p += 2;
        *p++ = rec->r.ver.version;
-       p += 7; /* skip reserved bytes and lock flags */
+       *p++ = rec->r.ver.marginals;
+       *p++ = rec->r.ver.completes;
+       *p++ = rec->r.ver.cert_depth;
+       p += 4; /* skip lock flags */
        ulongtobuf(p, rec->r.ver.created); p += 4;
        ulongtobuf(p, rec->r.ver.modified); p += 4;
        ulongtobuf(p, rec->r.ver.validated); p += 4;
@@ -1157,6 +1217,7 @@ tdbio_write_record( TRUSTREC *rec )
        ulongtobuf(p, rec->r.dir.cacherec); p += 4;
        *p++ = rec->r.dir.ownertrust;
        *p++ = rec->r.dir.dirflags;
+       *p++ = rec->r.dir.validity;
        assert( rec->r.dir.lid == recnum );
        break;
 
index e44f8c3..d2d369b 100644 (file)
 #define RECTYPE_FREE 254
 
 
-#define DIRF_CHECKED  1 /* has been checkd - other bits are valid */
+#define DIRF_CHECKED  1 /* has been checked - bits 1,2,3 are valid */
 #define DIRF_VALID    2 /* This key is valid:  There is at least */
                        /* one uid with a selfsignature or an revocation */
 #define DIRF_EXPIRED  4 /* the complete key has expired */
 #define DIRF_REVOKED  8 /* the complete key has been revoked */
+#define DIRF_VALVALID 16 /* The validity field is valid */
 
 #define KEYF_CHECKED  1 /* This key has been checked */
 #define KEYF_VALID    2 /* This is a valid (sub)key */
@@ -77,6 +78,9 @@ struct trust_record {
     union {
        struct {             /* version record: */
            byte version;    /* should be 2 */
+           byte  marginals;
+           byte  completes;
+           byte  cert_depth;
            ulong created;   /* timestamp of trustdb creation  */
            ulong modified;  /* timestamp of last modification */
            ulong validated; /* timestamp of last validation   */
@@ -94,6 +98,7 @@ struct trust_record {
            ulong cacherec; /* the cache record */
            byte ownertrust;
            byte dirflags;
+           byte validity; /* calculated trustlevel */
        } dir;
        struct {            /* primary public key record */
            ulong lid;
@@ -168,6 +173,7 @@ const char *tdbio_get_dbname(void);
 void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
 int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
 int tdbio_write_record( TRUSTREC *rec );
+int tdbio_db_matches_options(void);
 int tdbio_is_dirty(void);
 int tdbio_sync(void);
 int tdbio_begin_transaction(void);
index c145525..4cdb7e8 100644 (file)
@@ -42,8 +42,6 @@
 #include "i18n.h"
 #include "tdbio.h"
 
-#define MAX_CERT_DEPTH 5
-
 #if MAX_FINGERPRINT_LEN > 20
   #error Must change structure of trustdb
 #endif
@@ -67,7 +65,7 @@ typedef struct trust_info TRUST_INFO;
 struct trust_info {
     ulong    lid;
     byte     otrust; /* ownertrust (assigned trust) */
-    byte     trust; /* calculated trust (validity) */
+    byte     trust;  /* calculated trust (validity) */
 };
 
 typedef struct trust_seg_list *TRUST_SEG_LIST;
@@ -806,14 +804,15 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
                    continue; /* skip revoked signatures */
 
                /* visit every signer only once (a signer may have
-                * signed multizple user IDs */
+                * signed more than one user ID) */
                if( sigs_seen && ins_lid_table_item( sigs_seen,
                                                     rec.r.sig.sig[i].lid, 0) )
-                   continue; /* we alread have this one */
+                   continue; /* we already have this one */
 
                read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
                if( tmp.rectype != RECTYPE_DIR ) {
-                   log_info("oops: lid %lu: sig %lu has rectype %d"
+                   if( tmp.rectype != RECTYPE_SDIR )
+                       log_info("oops: lid %lu: sig %lu has rectype %d"
                             " - skipped\n",
                            drec->r.dir.lid, tmp.recnum, tmp.rectype );
                    continue;
@@ -892,7 +891,7 @@ verify_key( int max_depth, TRUSTREC *drec )
  * but nothing more is known.
  */
 static int
-do_check( TRUSTREC *dr, unsigned *trustlevel )
+do_check( TRUSTREC *dr, unsigned *validity )
 {
     if( !dr->r.dir.keylist ) {
        log_error(_("Ooops, no keys\n"));
@@ -903,10 +902,23 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
        return G10ERR_TRUSTDB;
     }
 
-    *trustlevel = verify_key( MAX_CERT_DEPTH, dr );
+    if( tdbio_db_matches_options()
+       && (dr->r.dir.dirflags & DIRF_VALVALID)
+       && dr->r.dir.validity )
+       *validity = dr->r.dir.validity;
+    else {
+       *validity = verify_key( opt.max_cert_depth, dr );
+       if( (*validity & TRUST_MASK) >= TRUST_UNDEFINED
+           && tdbio_db_matches_options() ) {
+           /* update the cached validity value */
+           dr->r.dir.validity = (*validity & TRUST_MASK);
+           dr->r.dir.dirflags |= DIRF_VALVALID;
+           write_record( dr );
+       }
+    }
 
     if( dr->r.dir.dirflags & DIRF_REVOKED )
-       *trustlevel |= TRUST_FLAG_REVOKED;
+       *validity |= TRUST_FLAG_REVOKED;
 
     return 0;
 }
@@ -1496,7 +1508,10 @@ query_trust_info( PKT_public_key *pk )
 /****************
  * Enumerate all keys, which are needed to build all trust paths for
  * the given key.  This function does not return the key itself or
- * the ultimate key.
+ * the ultimate key (the last point in cerificate chain).  Only
+ * certificate chains which ends up at an ultimately trusted key
+ * are listed. If ownertrust or validity is not NULL, the corresponding
+ * value for the returned LID is also returned in these variable(s).
  *
  *  1) create a void pointer and initialize it to NULL
  *  2) pass this void pointer by reference to this function.
@@ -1505,51 +1520,73 @@ query_trust_info( PKT_public_key *pk )
  *     to indicate EOF. LID does contain the next key used to build the web
  *  4) Always call this function a last time with LID set to NULL,
  *     so that it can free its context.
+ *
+ * Returns: -1 on EOF or the level of the returned LID
  */
 int
-enum_trust_web( void **context, ulong *lid )
+enum_cert_paths( void **context, ulong *lid,
+                unsigned *ownertrust, unsigned *validity )
 {
-  #if 0
     struct {
        int init;
+       TRUST_SEG_LIST tsl_head;
+       TRUST_SEG_LIST tsl;
+       int idx;
     } *ctx;
-    int rc;
-    int wipe=0;
-    TRUSTREC rec;
-    TRUST_INFO *tmppath;
-    TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
-    PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+    TRUST_SEG_LIST tsl;
+
+    if( !lid ) {  /* release the context */
+       if( *context ) {
+           TRUST_SEG_LIST tsl2;
+
+           ctx = *context;
+           for(tsl = ctx->tsl_head; tsl; tsl = tsl2 ) {
+               tsl2 = tsl->next;
+               m_free( tsl );
+           }
+           *context = NULL;
+       }
+       return -1;
+    }
 
     if( !*context ) {
-       asssert( *lid );
+       TRUST_INFO *tmppath;
+       TRUSTREC rec;
+
+       if( !lid )
+           return -1;
 
        ctx = m_alloc_clear( sizeof *ctx );
        *context = ctx;
        /* collect the paths */
        read_record( *lid, &rec, RECTYPE_DIR );
-       tmppath = m_alloc_clear( (MAX_CERT_DEPTH+1)* sizeof *tmppath );
-       trust_seg_list = NULL;
-       collect_paths( 0, MAX_CERT_DEPTH, 1, &rec, tmppath, &trust_seg_list );
+       tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
+       tsl = NULL;
+       collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl );
        m_free( tmppath );
        /* and now print them */
-       for(tsl = trust_seg_list; tsl; tsl = tsl->next ) {
-           print_path( tsl->pathlen, tsl->path );
-       }
+       ctx->tsl_head = tsl;
+       ctx->tsl = ctx->tsl_head;
+       ctx->idx = 0;
     }
     else
        ctx = *context;
 
-    if( !lid ) {  /* release the context */
-       if( *
-        /* release the list */
-        for(tsl = trust_seg_list; tsl; tsl = tsl2 ) {
-            tsl2 = tsl->next;
-            m_free( tsl );
-        }
-        trust_seg_list = NULL;
-    }
-   #endif
-    return -1; /* eof */
+    while( ctx->tsl && ctx->idx >= tsl->pathlen )  {
+       ctx->tsl = ctx->tsl->next;
+       ctx->idx = 0;
+    }
+    tsl = ctx->tsl;
+    if( !tsl )
+       return -1; /* eof */
+
+    if( ownertrust )
+       *ownertrust = tsl->path[ctx->idx].otrust;
+    if( validity )
+       *validity = tsl->path[ctx->idx].trust;
+    *lid = tsl->path[ctx->idx].lid;
+    ctx->idx++;
+    return ctx->idx-1;
 }
 
 
@@ -1671,7 +1708,7 @@ query_trust_record( PKT_public_key *pk )
     return get_dir_record( pk, &rec );
 }
 
-/* FIXME: Brauchen wir das?? */
+
 int
 clear_trust_checked_flag( PKT_public_key *pk )
 {
@@ -1682,11 +1719,14 @@ clear_trust_checked_flag( PKT_public_key *pk )
     if( rc )
        return rc;
 
-    if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
+    /* check whether they are already reset */
+    if(   !(rec.r.dir.dirflags & DIRF_CHECKED)
+       && !(rec.r.dir.dirflags & DIRF_VALVALID) )
        return 0;
 
     /* reset the flag */
     rec.r.dir.dirflags &= ~DIRF_CHECKED;
+    rec.r.dir.dirflags &= ~DIRF_VALVALID;
     write_record( &rec );
     do_sync();
     return 0;
@@ -2735,6 +2775,8 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
     if( rc )
        rc = tdbio_cancel_transaction();
     else {
+       drec.r.dir.dirflags |= DIRF_CHECKED;
+       drec.r.dir.dirflags &= ~DIRF_VALVALID;
        write_record( &drec );
        if( modified && tdbio_is_dirty() )
            *modified = 1;
index 4dc8b2c..04b2435 100644 (file)
@@ -50,7 +50,8 @@ void update_trustdb( void );
 int init_trustdb( int level, const char *dbname );
 int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
 int query_trust_info( PKT_public_key *pk );
-int enum_trust_web( void **context, ulong *lid );
+int enum_cert_paths( void **context, ulong *lid,
+                    unsigned *ownertrust, unsigned *validity );
 unsigned get_ownertrust( ulong lid );
 int get_ownertrust_info( ulong lid );
 byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n );
index 6d39d23..acb4de4 100644 (file)
@@ -45,6 +45,7 @@ typedef struct {
         int inarg;
         int stopped;
         const char *last;
+        void *aliases;
      } internal;           /* DO NOT CHANGE */
 } ARGPARSE_ARGS;
 
@@ -152,9 +153,10 @@ const char *memistr( const char *buf, size_t buflen, const char *sub );
 char *mem2str( char *, const void *, size_t);
 char *trim_spaces( char *string );
 int string_count_chr( const char *string, int c );
-int  set_native_charset( const char *newset );
+int set_native_charset( const char *newset );
 char *native_to_utf8( const char *string );
 char *utf8_to_native( const char *string );
+int  check_utf8_string( const char *string );
 
 #define stricmp(a,b) strcasecmp((a),(b))
 
index a75ef34..29870e9 100644 (file)
@@ -51,6 +51,7 @@
  *     struct {
  *         int index;
  *         const char *last;
+ *         void *aliases;
  *     } internal;               DO NOT CHANGE
  *  } ARGPARSE_ARGS;
  *
  *
  */
 
+typedef struct alias_def_s *ALIAS_DEF;
+struct alias_def_s {
+    ALIAS_DEF next;
+    char *name;   /* malloced buffer with name, \0, value */
+    const char *value; /* ptr into name */
+};
 
 static int  set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
 static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
@@ -139,7 +146,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
        arg->internal.index = 0;
        arg->internal.last = NULL;
        arg->internal.inarg = 0;
-       arg->internal.stopped= 0;
+       arg->internal.stopped = 0;
+       arg->internal.aliases = NULL;
        arg->err = 0;
        arg->flags |= 1<<15; /* mark initialized */
        if( *arg->argc < 0 )
@@ -160,6 +168,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
                s = "%s:%u: missing argument\n";
            else if( arg->r_opt == -7 )
                s = "%s:%u: invalid command\n";
+           else if( arg->r_opt == -10 )
+               s = "%s:%u: invalid alias definition\n";
            else
                s = "%s:%u: invalid option\n";
            log_error(s, filename, *lineno );
@@ -187,6 +197,16 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
 
 
 
+static void
+store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
+{
+    ALIAS_DEF a = m_alloc( sizeof *a );
+    a->name = name;
+    a->value = value;
+    a->next = (ALIAS_DEF)arg->internal.aliases;
+    (ALIAS_DEF)arg->internal.aliases = a;
+}
+
 /****************
  * Get options from a file.
  * Lines starting with '#' are comment lines.
@@ -194,6 +214,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
  * Valid keywords are all keywords from the long_opt list without
  * the leading dashes. The special keywords "help", "warranty" and "version"
  * are not valid here.
+ * The special keyword "alias" may be used to store alias definitions,
+ * which are later expanded like long options.
  * Caller must free returned strings.
  * If called with FP set to NULL command line args are parse instead.
  *
@@ -212,6 +234,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
     char *buffer = NULL;
     size_t buflen = 0;
     int inverse=0;
+    int in_alias=0;
 
     if( !fp ) /* same as arg_parse() in this case */
        return arg_parse( arg, opts );
@@ -234,9 +257,9 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
                        break;
                index = i;
                arg->r_opt = opts[index].short_opt;
-               if( inverse )
+               if( inverse ) /* this does not have an effect, hmmm */
                    arg->r_opt = -arg->r_opt;
-               if( !opts[index].short_opt )     /* unknown command/option */
+               if( !opts[index].short_opt )   /* unknown command/option */
                    arg->r_opt = (opts[index].flags & 256)? -7:-2;
                else if( (opts[index].flags & 8) ) /* no argument */
                    arg->r_opt = -3;           /* error */
@@ -245,7 +268,9 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
                break;
            }
            else if( state == 3 ) {            /* no argument found */
-               if( !(opts[index].flags & 7) ) /* does not take an argument */
+               if( in_alias )
+                   arg->r_opt = -3;           /* error */
+               else if( !(opts[index].flags & 7) ) /* does not take an arg */
                    arg->r_type = 0;           /* okay */
                else if( (opts[index].flags & 8) )  /* no optional argument */
                    arg->r_type = 0;           /* okay */
@@ -254,7 +279,28 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
                break;
            }
            else if( state == 4 ) {     /* have an argument */
-               if( !(opts[index].flags & 7) )  /* does not take an argument */
+               if( in_alias ) {
+                   if( !buffer )
+                       arg->r_opt = -6;
+                   else {
+                       char *p;
+
+                       buffer[i] = 0;
+                       p = strpbrk( buffer, " \t" );
+                       if( p ) {
+                           *p++ = 0;
+                           trim_spaces( p );
+                       }
+                       if( !p || !*p ) {
+                           m_free( buffer );
+                           arg->r_opt = -10;
+                       }
+                       else {
+                           store_alias( arg, buffer, p );
+                       }
+                   }
+               }
+               else if( !(opts[index].flags & 7) )  /* does not take an arg */
                    arg->r_opt = -6;        /* error */
                else {
                    if( !buffer ) {
@@ -296,8 +342,14 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
            index = i;
            arg->r_opt = opts[index].short_opt;
            if( !opts[index].short_opt ) {
-               arg->r_opt = (opts[index].flags & 256)? -7:-2;
-               state = -1;        /* skip rest of line and leave */
+               if( !strcmp( keyword, "alias" ) ) {
+                   in_alias = 1;
+                   state = 3;
+               }
+               else {
+                   arg->r_opt = (opts[index].flags & 256)? -7:-2;
+                   state = -1;        /* skip rest of line and leave */
+               }
            }
            else
                state = 3;
@@ -344,10 +396,12 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
 
 
 static int
-find_long_option( ARGPARSE_OPTS *opts, const char *keyword )
+find_long_option( ARGPARSE_ARGS *arg,
+                 ARGPARSE_OPTS *opts, const char *keyword )
 {
     int i;
     size_t n;
+    ALIAS_DEF a;
 
     /* Would be better if we can do a binary search, but it is not
        possible to reorder our option table because we would mess
@@ -358,7 +412,14 @@ find_long_option( ARGPARSE_OPTS *opts, const char *keyword )
     for(i=0; opts[i].short_opt; i++ )
        if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
            return i;
+   #if 0
+    /* see whether it is an alias */
+    for( a= argds->internal.aliases; a; a = a->next )
+       if( !strcmp( a->name, keyword) )
+           return what_do_we_return_here;
+   #endif
     /* not found, see whether it is an abbreviation */
+    /* aliases may not be abbreviated */
     n = strlen( keyword );
     for(i=0; opts[i].short_opt; i++ ) {
        if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
@@ -424,7 +485,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
        argpos = strchr( s+2, '=' );
        if( argpos )
            *argpos = 0;
-       i = find_long_option( opts, s+2 );
+       i = find_long_option( arg, opts, s+2 );
        if( argpos )
            *argpos = '=';
 
index 42d4711..917b90d 100644 (file)
@@ -126,7 +126,7 @@ make_dotlock( const char *file_to_lock, long timeout )
 int
 release_dotlock( const char *lockfile )
 {
-    int pid = rad_lockfile( lockfile );
+    int pid = read_lockfile( lockfile );
     if( pid == -1 ) {
        log_error( "release_dotlock: lockfile error");
        return -1;
index 82ec690..ce76038 100644 (file)
@@ -285,6 +285,20 @@ utf8_to_native( const char *string )
 }
 
 
+/****************
+ * check whether string is a valid UTF8 string.
+ * Returns 0 = Okay
+ *        1 = Too short
+ *        2 = invalid encoding
+ */
+int
+check_utf8_string( const char *string )
+{
+    /*fixme */
+    return 0;
+}
+
+
 /*********************************************
  ********** missing string functions *********
  *********************************************/