From cf477d0908cde1b22d218799782567efa784ea6b Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 19 Sep 2001 14:25:05 +0000 Subject: [PATCH] Bug fixes and Timo's patches --- AUTHORS | 3 + TODO | 2 +- g10/ChangeLog | 25 +++++++ g10/g10.c | 12 ++- g10/getkey.c | 2 +- g10/gpgv.c | 2 +- g10/hkp.c | 101 ++++++++++++++++++++++++- g10/hkp.h | 3 +- g10/import.c | 191 +++++++++++++++++++++++++++-------------------- g10/keyring.c | 28 ++++++- g10/keyring.o | Bin 56848 -> 57000 bytes g10/main.h | 8 +- g10/mainproc.c | 4 +- g10/passphrase.c | 138 ++++++++++++++++++++++++++++------ include/util.h | 3 +- util/ChangeLog | 15 ++++ util/iobuf.c | 56 +++++++++++--- util/miscutil.c | 13 +++- util/strgutil.c | 29 +++---- util/ttyio.c | 2 +- util/w32reg.c | 69 +++++++++++++---- 21 files changed, 549 insertions(+), 157 deletions(-) diff --git a/AUTHORS b/AUTHORS index 62076497a..22df2a5e4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -47,6 +47,9 @@ R Stefan Bellon Assignment (All patches to support RISC OS) +Timo Schulz Assignment + (util/w32reg.c, g10/passphrase.c, g10/hkp.c) + Tedi Heriyanto Translations [id] Thiago Jung Bauermann Translations [pt_BR] diff --git a/TODO b/TODO index 5108cfee5..72ced7b71 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ - * 12345678! does not work anymore. Same for +wordlist. + * Selection using +wordlist does not work. * Always use the primary key to sign other keys. diff --git a/g10/ChangeLog b/g10/ChangeLog index e71b6a049..abb59df05 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,30 @@ +2001-09-19 Werner Koch + + * passphrase.c (writen, readn) + (agent_open, agent_close) + (agent_get_passphrase) + (passphrase_clear_cache): Support for W32. Contributed by Timo. + + * import.c (import_one): Release keydb handles at 2 more places. + + * keyring.c (keyring_release): Close the iobuf. + (keyring_get_keyblock): Init ret_kb to NULL and store error contidion. + + * import.c (import_new_stats_handle): New. + (import_release_stats_handle): New. + (import_print_stats): Renamed from static fnc print_stats. + (import_keys, import_keys_stream): Add an optional status handle + arg and changed all callers. + * hkp.c (hkp_ask_import): Add an stats_handle arg and changed all + callers. + + * mainproc.c (print_pkenc_list): Use print_utf8_string2(). + 2001-09-18 Werner Koch + * g10.c: New command --refresh-keys. + * hkp.c (hkp_refresh_keys): New. Contributed by Timo Schulz. + * parse-packet.c (parse): Stop on impossible packet lengths. 2001-09-17 Werner Koch diff --git a/g10/g10.c b/g10/g10.c index 1646853a8..6c92f5675 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -113,6 +113,7 @@ enum cmd_and_opt_values { aNull = 0, aGenRandom, aPipeMode, aRefreshCaches, + aRefreshKeys, oTextmode, oFingerprint, @@ -260,6 +261,8 @@ static ARGPARSE_OPTS opts[] = { { aExport, "export" , 256, N_("export keys") }, { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, + { aRefreshKeys, "refresh-keys", 256, + N_("update all keys from a keyserver")}, { aExportAll, "export-all" , 256, "@" }, { aExportSecret, "export-secret-keys" , 256, "@" }, { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, @@ -798,6 +801,7 @@ main( int argc, char **argv ) case aFastImport: set_cmd( &cmd, aFastImport); break; case aSendKeys: set_cmd( &cmd, aSendKeys); break; case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; + case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; case aExport: set_cmd( &cmd, aExport); break; case aExportAll: set_cmd( &cmd, aExportAll); break; case aListKeys: set_cmd( &cmd, aListKeys); break; @@ -1473,7 +1477,7 @@ main( int argc, char **argv ) case aFastImport: case aImport: - import_keys( argc? argv:NULL, argc, (cmd == aFastImport) ); + import_keys( argc? argv:NULL, argc, (cmd == aFastImport), NULL ); break; case aExport: @@ -1492,6 +1496,12 @@ main( int argc, char **argv ) free_strlist(sl); break; + case aRefreshKeys: + if (argc) + wrong_args("--refresh-keys"); + hkp_refresh_keys (); + break; + case aExportSecret: sl = NULL; for( ; argc; argc--, argv++ ) diff --git a/g10/getkey.c b/g10/getkey.c index d514ad0f7..2faa27cc5 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -2211,7 +2211,7 @@ char* get_user_id_string_native( u32 *keyid ) { char *p = get_user_id_string( keyid ); - char *p2 = utf8_to_native( p, strlen(p) ); + char *p2 = utf8_to_native( p, strlen(p), 0 ); m_free(p); return p2; diff --git a/g10/gpgv.c b/g10/gpgv.c index 7d0ecc86f..e64b7576e 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -254,7 +254,7 @@ get_ownertrust_info( ulong lid ) * get them from a keyserver */ int -hkp_ask_import( u32 *keyid ) +hkp_ask_import( u32 *keyid, void *dummy ) { return -1; } diff --git a/g10/hkp.c b/g10/hkp.c index 38a262654..9ab6d791f 100644 --- a/g10/hkp.c +++ b/g10/hkp.c @@ -47,7 +47,7 @@ static int urlencode_filter( void *opaque, int control, * or other error codes. */ int -hkp_ask_import( u32 *keyid ) +hkp_ask_import( u32 *keyid, void *stats_handle) { struct http_context hd; char *request; @@ -85,7 +85,7 @@ hkp_ask_import( u32 *keyid ) : g10_errstr(rc) ); } else { - rc = import_keys_stream( hd.fp_read , 0 ); + rc = import_keys_stream( hd.fp_read , 0, stats_handle ); http_close( &hd ); } @@ -98,11 +98,14 @@ hkp_ask_import( u32 *keyid ) int hkp_import( STRLIST users ) { + void *stats_handle; + if( !opt.keyserver_name ) { log_error(_("no keyserver known (use option --keyserver)\n")); return -1; } + stats_handle = import_new_stats_handle (); for( ; users; users = users->next ) { KEYDB_SEARCH_DESC desc; @@ -116,9 +119,11 @@ hkp_import( STRLIST users ) * errorcounter ist not increaed and the program will return * with success - which is not good when this function is used. */ - if( hkp_ask_import( desc.u.kid ) ) + if( hkp_ask_import( desc.u.kid, stats_handle ) ) log_inc_errorcount(); } + import_print_stats (stats_handle); + import_release_stats_handle (stats_handle); return 0; } @@ -238,3 +243,93 @@ urlencode_filter( void *opaque, int control, return rc; } + +int +hkp_refresh_keys (void) +{ + KEYDB_HANDLE hd; + KBNODE node, keyblock = NULL; + PKT_public_key *pk; + u32 keyid[2]; + u32 *keys = NULL; + size_t n, nkeys=0, maxkeys=0; + void *stats_handle; + int rc = 0; + + /* fist take a snapshot of all keys */ + hd = keydb_new(0); + rc = keydb_search_first(hd); + if (rc) { + if (rc != -1) + log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); + goto leave; + } + + do { + if (!keys) { + maxkeys = 10000; + keys = m_alloc (maxkeys * sizeof *keys); + nkeys = 0; + } + else if ( nkeys == maxkeys ) { + maxkeys += 10000; + keys = m_realloc (keys, maxkeys * sizeof *keys); + } + + rc = keydb_get_keyblock (hd, &keyblock); + if (rc) { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + goto leave; + } + + node = keyblock; + if ( node->pkt->pkttype != PKT_PUBLIC_KEY) { + log_debug ("invalid pkttype %d encountered\n", + node->pkt->pkttype); + dump_kbnode (node); + release_kbnode(keyblock); + continue; + } + pk = node->pkt->pkt.public_key; + keyid_from_pk(pk, keyid); + release_kbnode(keyblock); + keyblock = NULL; + /* fixme: replace the linear search */ + for (n=0; n < nkeys; n++) { + if (keys[n] == keyid[1]) { + log_info (_("duplicate (short) key ID %08lX\n"), + (ulong)keyid[1]); + break; + } + } + if (n == nkeys) /* not a duplicate */ + keys[nkeys++] = keyid[1]; + } while ( !(rc = keydb_search_next(hd)) ); + if (rc == -1) + rc = 0; + if (rc) + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + keydb_release(hd); + hd = NULL; + + /* and now refresh them */ + stats_handle = import_new_stats_handle (); + log_info (_("%lu key(s) to refresh\n"), (ulong)nkeys); + for (n=0; n < nkeys; n++) { + /* Note: We do only use the short keyID */ + keyid[0] = 0; + keyid[1] = keys[n]; + if ( hkp_ask_import(keyid, stats_handle) ) + log_inc_errorcount(); + } + import_print_stats (stats_handle); + import_release_stats_handle (stats_handle); + + leave: + m_free (keys); + if (keyblock) + release_kbnode(keyblock); + keydb_release(hd); + return rc; +} + diff --git a/g10/hkp.h b/g10/hkp.h index 4f027882c..003f89965 100644 --- a/g10/hkp.h +++ b/g10/hkp.h @@ -22,9 +22,10 @@ #define G10_HKP_H 1 -int hkp_ask_import( u32 *keyid ); +int hkp_ask_import( u32 *keyid, void *stats_handle); int hkp_import( STRLIST users ); int hkp_export( STRLIST users ); +int hkp_refresh_keys (void); #endif /*G10_HKP_H*/ diff --git a/g10/import.c b/g10/import.c index 88abd30c1..ad9def008 100644 --- a/g10/import.c +++ b/g10/import.c @@ -37,7 +37,7 @@ #include "status.h" -static struct { +struct stats_s { ulong count; ulong no_user_id; ulong imported; @@ -51,16 +51,19 @@ static struct { ulong secret_imported; ulong secret_dups; ulong skipped_new_keys; -} stats; +}; -static int import( IOBUF inp, int fast, const char* fname, int allow_secret ); -static void print_stats(void); +static int import( IOBUF inp, int fast, const char* fname, + int allow_secret, struct stats_s *stats ); static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); static void remove_bad_stuff (KBNODE keyblock); -static int import_one( const char *fname, KBNODE keyblock, int fast ); -static int import_secret_one( const char *fname, KBNODE keyblock, int allow ); -static int import_revoke_cert( const char *fname, KBNODE node ); +static int import_one( const char *fname, KBNODE keyblock, int fast, + struct stats_s *stats); +static int import_secret_one( const char *fname, KBNODE keyblock, + int allow, struct stats_s *stats ); +static int import_revoke_cert( const char *fname, KBNODE node, + struct stats_s *stats); static int chk_self_sigs( const char *fname, KBNODE keyblock, PKT_public_key *pk, u32 *keyid ); static void mark_non_selfsigned_uids_valid( KBNODE keyblock, u32 *kid ); @@ -78,6 +81,18 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, const char *fname, u32 *keyid ); +void * +import_new_stats_handle (void) +{ + return m_alloc_clear ( sizeof (struct stats_s) ); +} + +void +import_release_stats_handle (void *p) +{ + m_free (p); +} + /**************** * Import the public keys from the given filename. Input may be armored. * This function rejects all keys which are not validly self signed on at @@ -110,12 +125,13 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, * */ void -import_keys( char **fnames, int nnames, int fast ) +import_keys( char **fnames, int nnames, int fast, void *stats_handle ) { int i; + struct stats_s *stats = stats_handle; - /* fixme: don't use static variables */ - memset( &stats, 0, sizeof( stats ) ); + if (!stats) + stats = import_new_stats_handle (); if( !fnames && !nnames ) nnames = 1; /* Ohh what a ugly hack to jump into the loop */ @@ -128,7 +144,8 @@ import_keys( char **fnames, int nnames, int fast ) if( !inp ) log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); else { - int rc = import( inp, fast, fname, opt.allow_secret_key_import ); + int rc = import( inp, fast, fname, + opt.allow_secret_key_import, stats ); iobuf_close(inp); if( rc ) log_error("import from `%s' failed: %s\n", fname, @@ -137,27 +154,37 @@ import_keys( char **fnames, int nnames, int fast ) if( !fname ) break; } - print_stats(); + if (!stats_handle) { + import_print_stats (stats); + import_release_stats_handle (stats); + } if( !fast ) sync_trustdb(); } int -import_keys_stream( IOBUF inp, int fast ) +import_keys_stream( IOBUF inp, int fast, void *stats_handle ) { int rc = 0; + struct stats_s *stats = stats_handle; - /* fixme: don't use static variables */ - memset( &stats, 0, sizeof( stats ) ); - rc = import( inp, fast, "[stream]", opt.allow_secret_key_import ); - print_stats(); + if (!stats) + stats = import_new_stats_handle (); + + rc = import( inp, fast, "[stream]", + opt.allow_secret_key_import, stats ); + if (!stats_handle) { + import_print_stats (stats); + import_release_stats_handle (stats); + } if( !fast ) sync_trustdb(); return rc; } static int -import( IOBUF inp, int fast, const char* fname, int allow_secret ) +import( IOBUF inp, int fast, const char* fname, int allow_secret, + struct stats_s *stats ) { PACKET *pending_pkt = NULL; KBNODE keyblock; @@ -174,12 +201,13 @@ import( IOBUF inp, int fast, const char* fname, int allow_secret ) while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { remove_bad_stuff (keyblock); if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) - rc = import_one( fname, keyblock, fast ); + rc = import_one( fname, keyblock, fast, stats ); else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) - rc = import_secret_one( fname, keyblock, allow_secret ); + rc = import_secret_one( fname, keyblock, + allow_secret, stats ); else if( keyblock->pkt->pkttype == PKT_SIGNATURE && keyblock->pkt->pkt.signature->sig_class == 0x20 ) - rc = import_revoke_cert( fname, keyblock ); + rc = import_revoke_cert( fname, keyblock, stats ); else { log_info( _("skipping block of type %d\n"), keyblock->pkt->pkttype ); @@ -187,8 +215,8 @@ import( IOBUF inp, int fast, const char* fname, int allow_secret ) release_kbnode(keyblock); if( rc ) break; - if( !(++stats.count % 100) && !opt.quiet ) - log_info(_("%lu keys so far processed\n"), stats.count ); + if( !(++stats->count % 100) && !opt.quiet ) + log_info(_("%lu keys so far processed\n"), stats->count ); } if( rc == -1 ) rc = 0; @@ -199,56 +227,58 @@ import( IOBUF inp, int fast, const char* fname, int allow_secret ) } -static void -print_stats() +void +import_print_stats (void *hd) { + struct stats_s *stats = hd; + if( !opt.quiet ) { - log_info(_("Total number processed: %lu\n"), stats.count ); - if( stats.skipped_new_keys ) + log_info(_("Total number processed: %lu\n"), stats->count ); + if( stats->skipped_new_keys ) log_info(_(" skipped new keys: %lu\n"), - stats.skipped_new_keys ); - if( stats.no_user_id ) - log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id ); - if( stats.imported || stats.imported_rsa ) { - log_info(_(" imported: %lu"), stats.imported ); - if( stats.imported_rsa ) - fprintf(stderr, " (RSA: %lu)", stats.imported_rsa ); + stats->skipped_new_keys ); + if( stats->no_user_id ) + log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); + if( stats->imported || stats->imported_rsa ) { + log_info(_(" imported: %lu"), stats->imported ); + if( stats->imported_rsa ) + fprintf(stderr, " (RSA: %lu)", stats->imported_rsa ); putc('\n', stderr); } - if( stats.unchanged ) - log_info(_(" unchanged: %lu\n"), stats.unchanged ); - if( stats.n_uids ) - log_info(_(" new user IDs: %lu\n"), stats.n_uids ); - if( stats.n_subk ) - log_info(_(" new subkeys: %lu\n"), stats.n_subk ); - if( stats.n_sigs ) - log_info(_(" new signatures: %lu\n"), stats.n_sigs ); - if( stats.n_revoc ) - log_info(_(" new key revocations: %lu\n"), stats.n_revoc ); - if( stats.secret_read ) - log_info(_(" secret keys read: %lu\n"), stats.secret_read ); - if( stats.secret_imported ) - log_info(_(" secret keys imported: %lu\n"), stats.secret_imported ); - if( stats.secret_dups ) - log_info(_(" secret keys unchanged: %lu\n"), stats.secret_dups ); + if( stats->unchanged ) + log_info(_(" unchanged: %lu\n"), stats->unchanged ); + if( stats->n_uids ) + log_info(_(" new user IDs: %lu\n"), stats->n_uids ); + if( stats->n_subk ) + log_info(_(" new subkeys: %lu\n"), stats->n_subk ); + if( stats->n_sigs ) + log_info(_(" new signatures: %lu\n"), stats->n_sigs ); + if( stats->n_revoc ) + log_info(_(" new key revocations: %lu\n"), stats->n_revoc ); + if( stats->secret_read ) + log_info(_(" secret keys read: %lu\n"), stats->secret_read ); + if( stats->secret_imported ) + log_info(_(" secret keys imported: %lu\n"), stats->secret_imported ); + if( stats->secret_dups ) + log_info(_(" secret keys unchanged: %lu\n"), stats->secret_dups ); } if( is_status_enabled() ) { char buf[13*20]; sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - stats.count, - stats.no_user_id, - stats.imported, - stats.imported_rsa, - stats.unchanged, - stats.n_uids, - stats.n_subk, - stats.n_sigs, - stats.n_revoc, - stats.secret_read, - stats.secret_imported, - stats.secret_dups, - stats.skipped_new_keys ); + stats->count, + stats->no_user_id, + stats->imported, + stats->imported_rsa, + stats->unchanged, + stats->n_uids, + stats->n_subk, + stats->n_sigs, + stats->n_revoc, + stats->secret_read, + stats->secret_imported, + stats->secret_dups, + stats->skipped_new_keys ); write_status_text( STATUS_IMPORT_RES, buf ); } } @@ -373,7 +403,8 @@ remove_bad_stuff (KBNODE keyblock) * which called g10. */ static int -import_one( const char *fname, KBNODE keyblock, int fast ) +import_one( const char *fname, KBNODE keyblock, int fast, + struct stats_s *stats ) { PKT_public_key *pk; PKT_public_key *pk_orig; @@ -422,7 +453,7 @@ import_one( const char *fname, KBNODE keyblock, int fast ) (ulong)keyid[1]); log_info(_("this may be caused by a missing self-signature\n")); } - stats.no_user_id++; + stats->no_user_id++; return 0; } @@ -439,7 +470,7 @@ import_one( const char *fname, KBNODE keyblock, int fast ) log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] ); rc = 0; fast = 1; /* so that we don't get into the trustdb update */ - stats.skipped_new_keys++; + stats->skipped_new_keys++; } else if( rc ) { /* insert this key */ KEYDB_HANDLE hd = keydb_new (0); @@ -447,6 +478,7 @@ import_one( const char *fname, KBNODE keyblock, int fast ) rc = keydb_locate_writable (hd, NULL); if (rc) { log_error (_("no writable keyring found: %s\n"), g10_errstr (rc)); + keydb_release (hd); return G10ERR_GENERAL; } if( opt.verbose > 1 ) @@ -464,9 +496,9 @@ import_one( const char *fname, KBNODE keyblock, int fast ) write_status_text( STATUS_IMPORTED, us ); m_free(us); } - stats.imported++; + stats->imported++; if( is_RSA( pk->pubkey_algo ) ) - stats.imported_rsa++; + stats->imported_rsa++; new_key = 1; } else { /* merge */ @@ -526,7 +558,6 @@ import_one( const char *fname, KBNODE keyblock, int fast ) if (rc) log_error (_("error writing keyring `%s': %s\n"), keydb_get_resource_name (hd), g10_errstr(rc) ); - keydb_release (hd); hd = NULL; /* we are ready */ if( !opt.quiet ) { if( n_uids == 1 ) @@ -549,15 +580,16 @@ import_one( const char *fname, KBNODE keyblock, int fast ) (ulong)keyid[1], n_subk ); } - stats.n_uids +=n_uids; - stats.n_sigs +=n_sigs; - stats.n_subk +=n_subk; + stats->n_uids +=n_uids; + stats->n_sigs +=n_sigs; + stats->n_subk +=n_subk; } else { if( !opt.quiet ) log_info( _("key %08lX: not changed\n"), (ulong)keyid[1] ); - stats.unchanged++; + stats->unchanged++; } + keydb_release (hd); hd = NULL; } if( !rc && !fast ) { rc = query_trust_record( new_key? pk : pk_orig ); @@ -589,7 +621,8 @@ import_one( const char *fname, KBNODE keyblock, int fast ) * with the trust calculation. */ static int -import_secret_one( const char *fname, KBNODE keyblock, int allow ) +import_secret_one( const char *fname, KBNODE keyblock, int allow, + struct stats_s *stats) { PKT_secret_key *sk; KBNODE node, uidnode; @@ -615,7 +648,7 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow ) uidnode->pkt->pkt.user_id->len ); putc('\n', stderr); } - stats.secret_read++; + stats->secret_read++; if (!allow) { log_info ( _("secret key %08lX not imported " "(use %s to allow for it)\n"), @@ -650,12 +683,12 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow ) /* we are ready */ if( !opt.quiet ) log_info( _("key %08lX: secret key imported\n"), (ulong)keyid[1]); - stats.secret_imported++; + stats->secret_imported++; } else if( !rc ) { /* we can't merge secret keys */ log_error( _("key %08lX: already in secret keyring\n"), (ulong)keyid[1]); - stats.secret_dups++; + stats->secret_dups++; } else log_error( _("key %08lX: secret key not found: %s\n"), @@ -669,7 +702,7 @@ import_secret_one( const char *fname, KBNODE keyblock, int allow ) * Import a revocation certificate; this is a single signature packet. */ static int -import_revoke_cert( const char *fname, KBNODE node ) +import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) { PKT_public_key *pk=NULL; KBNODE onode, keyblock = NULL; @@ -759,7 +792,7 @@ import_revoke_cert( const char *fname, KBNODE node ) if( !opt.quiet ) log_info( _("key %08lX: revocation certificate imported\n"), (ulong)keyid[1]); - stats.n_revoc++; + stats->n_revoc++; if( clear_trust_checked_flag( pk ) ) { /* seems that we have to insert the record first */ rc = insert_trust_record( keyblock ); diff --git a/g10/keyring.c b/g10/keyring.c index 9186a5ef2..fc4412d76 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -122,6 +122,7 @@ keyring_release (KEYRING_HANDLE hd) active_handles--; m_free (hd->word_match.name); m_free (hd->word_match.pattern); + iobuf_close (hd->current.iobuf); m_free (hd); } @@ -224,6 +225,9 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) int pk_no = 0; int uid_no = 0; + if (ret_kb) + *ret_kb = NULL; + if (!hd->found.kr) return -1; /* no successful search */ @@ -302,6 +306,13 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) free_packet (pkt); m_free (pkt); iobuf_close(a); + + /* Make sure that future search operations fail immediately when + * we know that we are working on a invalid keyring + */ + if (rc == G10ERR_INV_KEYRING) + hd->current.error = rc; + return rc; } @@ -355,6 +366,13 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) if (!fname) return G10ERR_GENERAL; + /* close this one otherwise we will lose the position for + * a next search. Fixme: it would be better to adjust the position + * after the write opertions. + */ + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + /* do the insert */ rc = do_copy (1, fname, kb, hd->secret, 0, 0 ); return rc; @@ -379,6 +397,13 @@ keyring_delete_keyblock (KEYRING_HANDLE hd) BUG (); } + /* close this one otherwise we will lose the position for + * a next search. Fixme: it would be better to adjust the position + * after the write opertions. + */ + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + /* do the delete */ rc = do_copy (2, hd->found.kr->fname, NULL, hd->secret, hd->found.offset, hd->found.n_packets ); @@ -419,7 +444,8 @@ prepare_search (KEYRING_HANDLE hd) return hd->current.error; /* still in error state */ if (hd->current.kr && !hd->current.eof) { - assert ( hd->current.iobuf); + if ( !hd->current.iobuf ) + return G10ERR_GENERAL; /* position invalid after a modify */ return 0; /* okay */ } diff --git a/g10/keyring.o b/g10/keyring.o index ff1e2ef621bd846318d50510820feb91aaa19f07..24f1f0460b6770f555a2ebbb8aed7475afca73ae 100644 GIT binary patch delta 10947 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 RutRvZaa!KXf9I1g{tw)GmSz9| diff --git a/g10/main.h b/g10/main.h index 43dd72ee3..02248a69f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -125,8 +125,12 @@ KBNODE make_comment_node( const char *s ); KBNODE make_mpi_comment_node( const char *s, MPI a ); /*-- import.c --*/ -void import_keys( char **fnames, int nnames, int fast ); -int import_keys_stream( IOBUF inp, int fast ); +void import_keys( char **fnames, int nnames, int fast, void *stats_hd ); +int import_keys_stream( IOBUF inp, int fast, void *stats_hd ); +void *import_new_stats_handle (void); +void import_release_stats_handle (void *p); +void import_print_stats (void *hd); + int collapse_uids( KBNODE *keyblock ); /*-- export.c --*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index 8bffddc50..25d1c60cc 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -380,7 +380,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) strtimestamp(pk->timestamp) ); fputs(" \"", log_stream() ); p = get_user_id( list->kid, &n ); - print_string( log_stream(), p, n, '"' ); + print_utf8_string2 ( log_stream(), p, n, '"' ); m_free(p); fputs("\"\n", log_stream() ); } @@ -1271,7 +1271,7 @@ check_sig_and_print( CTX c, KBNODE node ) rc = do_check_sig(c, node, NULL ); if( rc == G10ERR_NO_PUBKEY && opt.keyserver_name && opt.auto_key_retrieve) { - if( !hkp_ask_import( sig->keyid ) ) + if( !hkp_ask_import( sig->keyid, NULL ) ) rc = do_check_sig(c, node, NULL ); } if( !rc || rc == G10ERR_BAD_SIGN ) { diff --git a/g10/passphrase.c b/g10/passphrase.c index 6ec3cb10f..a9631bb2b 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -82,6 +82,11 @@ static char *fd_passwd = NULL; static char *next_pw = NULL; static char *last_pw = NULL; +#ifdef __MINGW32__ +static int read_fd = 0; +static int write_fd = 0; +#endif + static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ); int @@ -153,10 +158,27 @@ read_passphrase_from_fd( int fd ) fd_passwd = pw; } -#if !defined(HAVE_DOSISH_SYSTEM) && !defined(__riscos__) static int writen ( int fd, const void *buf, size_t nbytes ) { +#ifdef __MINGW32__ + DWORD nwritten, nleft = nbytes; + + while (nleft > 0) { + if ( !WriteFile( (HANDLE)write_fd, buf, nleft, &nwritten, NULL) ) { + log_error("write failed: ec=%d\n", (int)GetLastError()); + return -1; + } + /*log_info("** WriteFile fd=%d nytes=%d nwritten=%d\n", + write_fd, nbytes, (int)nwritten);*/ + Sleep(100); + + nleft -= nwritten; + buf = (const BYTE *)buf + nwritten; + } +#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + /* not implemented */ +#else size_t nleft = nbytes; int nwritten; @@ -166,13 +188,15 @@ writen ( int fd, const void *buf, size_t nbytes ) if ( errno == EINTR ) nwritten = 0; else { - log_error ( "writen() failed: %s\n", strerror (errno) ); + log_error ( "write() failed: %s\n", strerror (errno) ); return -1; } } nleft -= nwritten; buf = (const char*)buf + nwritten; } +#endif + return 0; } @@ -180,6 +204,29 @@ writen ( int fd, const void *buf, size_t nbytes ) static int readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) { +#ifdef __MINGW32__ + DWORD nread, nleft = buflen; + + while (nleft > 0) { + if ( !ReadFile( (HANDLE)read_fd, buf, nleft, &nread, NULL) ) { + log_error("read() error: ec=%d\n", (int)GetLastError()); + return -1; + } + if (!nread || GetLastError() == ERROR_BROKEN_PIPE) + break; + /*log_info("** ReadFile fd=%d buflen=%d nread=%d\n", + read_fd, buflen, (int)nread);*/ + Sleep(100); + + nleft -= nread; + buf = (BYTE *)buf + nread; + } + if (ret_nread) + *ret_nread = buflen - nleft; + +#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + /* not implemented */ +#else size_t nleft = buflen; int nread; char *p; @@ -202,6 +249,8 @@ readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) } if( ret_nread ) *ret_nread = buflen - nleft; +#endif + return 0; } @@ -213,6 +262,50 @@ readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) static int agent_open (void) { +#ifdef __MINGW32__ + int fd; + char *infostr, *p; + HANDLE h; + char pidstr[128]; + + if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentPID")) + || *infostr == '0') { + log_error( _("gpg-agent is not available in this session\n")); + return -1; + } + free(infostr); + + sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId()); + if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentCID", pidstr)) { + log_error( _("can't set client pid for the agent\n") ); + return -1; + } + h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); + SetEvent(h); + Sleep(50); /* some time for the server */ + if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentReadFD")) ) { + log_error( _("can't get server read FD for the agent\n") ); + return -1; + } + read_fd = atol(p); + free(p); + if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentWriteFD")) ) { + log_error ( _("can't get server write FD for the agent\n") ); + return -1; + } + write_fd = atol(p); + free(p); + fd = 0; + + if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { + fd = -1; + +#else /* Posix */ + int fd; char *infostr, *p; struct sockaddr_un client_addr; @@ -226,18 +319,18 @@ agent_open (void) infostr = m_strdup ( infostr ); if ( !(p = strchr ( infostr, ':')) || p == infostr || (p-infostr)+1 >= sizeof client_addr.sun_path ) { - log_error (_("malformed GPG_AGENT_INFO environment variable\n")); + log_error( _("malformed GPG_AGENT_INFO environment variable\n")); m_free (infostr ); return -1; } *p = 0; - + if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { log_error ("can't create socket: %s\n", strerror(errno) ); m_free (infostr ); return -1; } - + memset( &client_addr, 0, sizeof client_addr ); client_addr.sun_family = AF_UNIX; strcpy( client_addr.sun_path, infostr ); @@ -257,15 +350,22 @@ agent_open (void) close (fd); fd = -1; } +#endif + return fd; } + static void agent_close ( int fd ) { +#ifdef __MINGW32__ + HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); + ResetEvent(h); +#else close (fd); +#endif } -#endif /* !HAVE_DOSISH_SYSTEM && !__riscos__ */ /* @@ -277,22 +377,21 @@ agent_close ( int fd ) static char * agent_get_passphrase ( u32 *keyid, int mode ) { - #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - return NULL; - #else - +#if defined(__riscos__) + return NULL; +#else size_t n; char *atext; char buf[50]; int fd = -1; - size_t nread; + int nread; u32 reply; char *pw = NULL; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); byte fpr[MAX_FINGERPRINT_LEN]; #if MAX_FINGERPRINT_LEN < 20 - #error agent needs a 20 byte fingerprint +#error agent needs a 20 byte fingerprint #endif memset (fpr, 0, MAX_FINGERPRINT_LEN ); @@ -344,13 +443,10 @@ agent_get_passphrase ( u32 *keyid, int mode ) atext = m_strdup ( _("Enter passphrase\n") ); else atext = m_strdup ( _("Repeat passphrase\n") ); - - - + if ( (fd = agent_open ()) == -1 ) goto failure; - n = 4 + 20 + strlen (atext); u32tobuf (buf, n ); u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE ); @@ -358,7 +454,7 @@ agent_get_passphrase ( u32 *keyid, int mode ) if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) goto failure; m_free (atext); atext = NULL; - + /* get response */ if ( readn ( fd, buf, 12, &nread ) ) goto failure; @@ -418,7 +514,7 @@ agent_get_passphrase ( u32 *keyid, int mode ) free_public_key( pk ); return NULL; - #endif +#endif /* Posix or W32 */ } /* @@ -427,9 +523,9 @@ agent_get_passphrase ( u32 *keyid, int mode ) void passphrase_clear_cache ( u32 *keyid, int algo ) { - #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) +#if defined(__riscos__) return ; - #else +#else size_t n; char buf[50]; int fd = -1; @@ -487,7 +583,7 @@ passphrase_clear_cache ( u32 *keyid, int algo ) if ( fd != -1 ) agent_close (fd); free_public_key( pk ); - #endif +#endif /* Posix or W32 */ } diff --git a/include/util.h b/include/util.h index eafcabcf4..bd236796e 100644 --- a/include/util.h +++ b/include/util.h @@ -157,6 +157,7 @@ const char *strtimestamp( u32 stamp ); /* GMT */ const char *asctimestamp( u32 stamp ); /* localized */ void print_string( FILE *fp, const byte *p, size_t n, int delim ); void print_utf8_string( FILE *fp, const byte *p, size_t n ); +void print_utf8_string2( FILE *fp, const byte *p, size_t n, int delim); char *make_printable_string( const byte *p, size_t n, int delim ); int answer_is_yes( const char *s ); int answer_is_yes_no_quit( const char *s ); @@ -184,7 +185,7 @@ int string_count_chr( const char *string, int c ); int set_native_charset( const char *newset ); const char* get_native_charset(void); char *native_to_utf8( const char *string ); -char *utf8_to_native( const char *string, size_t length ); +char *utf8_to_native( const char *string, size_t length, int delim); int check_utf8_string( const char *string ); int ascii_isupper (int c); diff --git a/util/ChangeLog b/util/ChangeLog index 76a7ced53..fd6ce4146 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,18 @@ +2001-09-19 Werner Koch + + * w32reg.c (get_root_key): New. + (read_w32_registry_string): Use it here. + (write_w32_registry_string): New. Contributed by Timo. + + * iobuf.c (iobuf_ioctl): New command to disable fd + caching. Implemented no_cache flag where needed. + (iobuf_sockopen): Always set no_cache flag. + + * strgutil.c (utf8_to_native): Add a delim arg and changed all + callers. Make sure that quoting is done when translation is + disabled. + * miscutil.c (print_utf8_string2): New. + 2001-09-17 Werner Koch * miscutil.c (print_string): Use explicit ranges and not iscntrl(). diff --git a/util/iobuf.c b/util/iobuf.c index db0a31568..60ae6c866 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -58,6 +58,7 @@ typedef struct { FILE *fp; /* open file handle */ int keep_open; + int no_cache; int print_only_name; /* flags indicating that fname is not a real file*/ char fname[1]; /* name of the file */ } file_filter_ctx_t ; @@ -80,6 +81,7 @@ typedef struct { FILEP_OR_FD fp; /* open file handle */ int keep_open; + int no_cache; int eof_seen; int print_only_name; /* flags indicating that fname is not a real file*/ char fname[1]; /* name of the file */ @@ -98,6 +100,7 @@ typedef struct { int sock; int keep_open; + int no_cache; int eof_seen; int print_only_name; /* flags indicating that fname is not a real file*/ char fname[1]; /* name of the file */ @@ -142,6 +145,8 @@ fd_cache_invalidate (const char *fname) for (cc=close_cache; cc; cc = cc->next ) { if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { + if( DBG_IOBUF ) + log_debug (" did (%s)\n", cc->fname); #ifdef HAVE_DOSISH_SYSTEM CloseHandle (cc->fp); #else @@ -225,19 +230,21 @@ fd_cache_close (const char *fname, FILEP_OR_FD fp) close(fp); #endif if( DBG_IOBUF ) - log_debug ("fd_cache_close (%s) immediately\n", fname); + log_debug ("fd_cache_close (%p) real\n", fp); return; } /* try to reuse a slot */ for (cc=close_cache; cc; cc = cc->next ) { if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) { cc->fp = fp; + if( DBG_IOBUF ) + log_debug ("fd_cache_close (%s) used existing slot\n", fname); return; } } /* add a new one */ if( DBG_IOBUF ) - log_debug ("fd_cache_close (%s) new\n", fname); + log_debug ("fd_cache_close (%s) new slot created\n", fname); cc = m_alloc_clear (sizeof *cc + strlen (fname)); strcpy (cc->fname, fname); cc->fp = fp; @@ -259,7 +266,7 @@ fd_cache_open (const char *fname, const char *mode) FILEP_OR_FD fp = cc->fp; cc->fp = INVALID_FP; if( DBG_IOBUF ) - log_debug ("fd_cache_open (%s) hit\n", fname); + log_debug ("fd_cache_open (%s) using cached fp\n", fname); #ifdef HAVE_DOSISH_SYSTEM if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) { log_error ("rewind file failed on handle %p: ec=%d\n", @@ -276,7 +283,7 @@ fd_cache_open (const char *fname, const char *mode) } } if( DBG_IOBUF ) - log_debug ("fd_cache_open (%s) miss\n", fname); + log_debug ("fd_cache_open (%s) not cached\n", fname); return direct_open (fname, mode); } @@ -350,7 +357,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) *ret_len = nbytes; } else if( control == IOBUFCTRL_INIT ) { - a->keep_open = 0; + a->keep_open = a->no_cache = 0; } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "file_filter"; @@ -463,6 +470,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) else if ( control == IOBUFCTRL_INIT ) { a->eof_seen = 0; a->keep_open = 0; + a->no_cache = 0; } else if ( control == IOBUFCTRL_DESC ) { *(char**)buf = "file_filter(fd)"; @@ -473,14 +481,14 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) if( DBG_IOBUF ) log_debug("%s: close handle %p\n", a->fname, f ); if (!a->keep_open) - fd_cache_close (a->fname, f); + fd_cache_close (a->no_cache?NULL:a->fname, f); } #else if ( (int)f != 0 && (int)f != 1 ) { if( DBG_IOBUF ) log_debug("%s: close fd %d\n", a->fname, f ); if (!a->keep_open) - fd_cache_close (a->fname, f); + fd_cache_close (a->no_cache?NULL:a->fname, f); } f = INVALID_FP; #endif @@ -550,6 +558,7 @@ sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) else if ( control == IOBUFCTRL_INIT ) { a->eof_seen = 0; a->keep_open = 0; + a->no_cache = 0; } else if ( control == IOBUFCTRL_DESC ) { *(char**)buf = "sock_filter"; @@ -1096,8 +1105,8 @@ iobuf_fdopen( int fd, const char *mode ) IOBUF iobuf_sockopen ( int fd, const char *mode ) { -#ifdef __MINGW32__ IOBUF a; +#ifdef __MINGW32__ sock_filter_ctx_t *scx; size_t len; @@ -1112,10 +1121,12 @@ iobuf_sockopen ( int fd, const char *mode ) sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len ); if( DBG_IOBUF ) log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname); - return a; #else - return iobuf_fdopen (fd, mode); + a = iobuf_fdopen (fd, mode); #endif + if (a) + iobuf_ioctl (a,3,1,NULL); /* disable fd caching */ + return a; } /**************** @@ -1226,6 +1237,9 @@ int iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ) { if ( cmd == 1 ) { /* keep system filepointer/descriptor open */ + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n", + a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval ); for( ; a; a = a->chain ) if( !a->chain && a->filter == file_filter ) { file_filter_ctx_t *b = a->filter_ov; @@ -1241,6 +1255,9 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ) #endif } else if ( cmd == 2 ) { /* invalidate cache */ + if( DBG_IOBUF ) + log_debug("iobuf-*.*: ioctl `%s' invalidate\n", + ptrval? (char*)ptrval:"?"); if ( !a && !intval && ptrval ) { #ifndef FILE_FILTER_USES_STDIO fd_cache_invalidate (ptrval); @@ -1248,6 +1265,24 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ) return 0; } } + else if ( cmd == 3 ) { /* disallow/allow caching */ + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n", + a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval ); + for( ; a; a = a->chain ) + if( !a->chain && a->filter == file_filter ) { + file_filter_ctx_t *b = a->filter_ov; + b->no_cache = intval; + return 0; + } + #ifdef __MINGW32__ + else if( !a->chain && a->filter == sock_filter ) { + sock_filter_ctx_t *b = a->filter_ov; + b->no_cache = intval; + return 0; + } + #endif + } return -1; } @@ -1536,7 +1571,6 @@ iobuf_flush(IOBUF a) if( a->directfp ) return 0; - /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/ if( a->use == 3 ) { /* increase the temp buffer */ char *newbuf; size_t newsize = a->d.size + 8192; diff --git a/util/miscutil.c b/util/miscutil.c index 05beab0d6..3bff721c1 100644 --- a/util/miscutil.c +++ b/util/miscutil.c @@ -207,7 +207,7 @@ print_string( FILE *fp, const byte *p, size_t n, int delim ) * Print an UTF8 string to FP and filter all control characters out. */ void -print_utf8_string( FILE *fp, const byte *p, size_t n ) +print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim ) { size_t i; char *buf; @@ -218,12 +218,19 @@ print_utf8_string( FILE *fp, const byte *p, size_t n ) break; } if( i < n ) { - buf = utf8_to_native( p, n ); + buf = utf8_to_native ( p, n, delim ); + /*(utf8 conversion already does the control character quoting)*/ fputs( buf, fp ); m_free( buf ); } else - print_string( fp, p, n, 0 ); + print_string( fp, p, n, delim ); +} + +void +print_utf8_string( FILE *fp, const byte *p, size_t n ) +{ + print_utf8_string2 (fp, p, n, 0); } /**************** diff --git a/util/strgutil.c b/util/strgutil.c index 5e978eb04..7b72bbbe3 100644 --- a/util/strgutil.c +++ b/util/strgutil.c @@ -439,11 +439,13 @@ native_to_utf8( const char *string ) /**************** - * Convert string, which is in UTF8 to native encoding. - * illegal encodings by some "\xnn" and quote all control characters - */ + * Convert string, which is in UTF8 to native encoding. illegal + * encodings by some "\xnn" and quote all control characters. A + * character with value DELIM will always be quoted, it must be a + * vanilla ASCII character. + */ char * -utf8_to_native( const char *string, size_t length ) +utf8_to_native( const char *string, size_t length, int delim ) { int nleft; int i; @@ -456,13 +458,6 @@ utf8_to_native( const char *string, size_t length ) size_t slen; int resync = 0; - if (no_translation) { - buffer = m_alloc (length+1); - memcpy (buffer, string, length); - buffer[length] = 0; /* make sure it is a string */ - return buffer; - } - /* 1. pass (p==NULL): count the extended utf-8 characters */ /* 2. pass (p!=NULL): create string */ for( ;; ) { @@ -481,7 +476,7 @@ utf8_to_native( const char *string, size_t length ) } if( !nleft ) { if( !(*s & 0x80) ) { /* plain ascii */ - if( iscntrl( *s ) ) { + if( *s < 0x20 || *s == 0x7f || *s == delim) { n++; if( p ) *p++ = '\\'; @@ -564,7 +559,15 @@ utf8_to_native( const char *string, size_t length ) val <<= 6; val |= *s & 0x3f; if( !--nleft ) { /* ready */ - if( active_charset ) { /* table lookup */ + if (no_translation) { + if( p ) { + for(i=0; i < encidx; i++ ) + *p++ = encbuf[i]; + } + n += encidx; + encidx = 0; + } + else if( active_charset ) { /* table lookup */ for(i=0; i < 128; i++ ) { if( active_charset[i] == val ) break; diff --git a/util/ttyio.c b/util/ttyio.c index 513026d43..c5f875314 100644 --- a/util/ttyio.c +++ b/util/ttyio.c @@ -257,7 +257,7 @@ tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) break; } if( i < n ) { - buf = utf8_to_native( p, n ); + buf = utf8_to_native( p, n, 0 ); if( strlen( buf ) > max_n ) { buf[max_n] = 0; } diff --git a/util/w32reg.c b/util/w32reg.c index 0cf38090f..a0da975ef 100644 --- a/util/w32reg.c +++ b/util/w32reg.c @@ -29,6 +29,31 @@ #include "util.h" #include "memory.h" +static HKEY +get_root_key(const char *root) +{ + HKEY root_key; + + if( !root ) + root_key = HKEY_CURRENT_USER; + else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) + root_key = HKEY_CLASSES_ROOT; + else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) + root_key = HKEY_CURRENT_USER; + else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) + root_key = HKEY_LOCAL_MACHINE; + else if( !strcmp( root, "HKEY_USERS" ) ) + root_key = HKEY_USERS; + else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) + root_key = HKEY_PERFORMANCE_DATA; + else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + return root_key; +} + /**************** * Return a string from the Win32 Registry or NULL in case of @@ -44,21 +69,7 @@ read_w32_registry_string( const char *root, const char *dir, const char *name ) DWORD n1, nbytes; char *result = NULL; - if( !root ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) - root_key = HKEY_CLASSES_ROOT; - else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) - root_key = HKEY_LOCAL_MACHINE; - else if( !strcmp( root, "HKEY_USERS" ) ) - root_key = HKEY_USERS; - else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) - root_key = HKEY_PERFORMANCE_DATA; - else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) - root_key = HKEY_CURRENT_CONFIG; - else + if ( !(root_key = get_root_key(root) ) ) return NULL; if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) @@ -82,7 +93,35 @@ read_w32_registry_string( const char *root, const char *dir, const char *name ) } +int +write_w32_registry_string(const char *root, const char *dir, + const char *name, const char *value) +{ + HKEY root_key, reg_key; + + if ( !(root_key = get_root_key(root) ) ) + return -1; + if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key ) + != ERROR_SUCCESS ) + return -1; + + if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) { + if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) { + RegCloseKey(reg_key); + return -1; + } + if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) { + RegCloseKey(reg_key); + return -1; + } + } + RegCloseKey( reg_key ); + + return 0; +} #endif /* __MINGW32__ */