diff options
author | Werner Koch <[email protected]> | 2001-09-19 14:25:05 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-09-19 14:25:05 +0000 |
commit | cf477d0908cde1b22d218799782567efa784ea6b (patch) | |
tree | d7ff0d0524c5da1477c4c075ec0f3a15672bdf8c | |
parent | Check for garbled packets (diff) | |
download | gnupg-cf477d0908cde1b22d218799782567efa784ea6b.tar.gz gnupg-cf477d0908cde1b22d218799782567efa784ea6b.zip |
Bug fixes and Timo's patches
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | g10/ChangeLog | 25 | ||||
-rw-r--r-- | g10/g10.c | 12 | ||||
-rw-r--r-- | g10/getkey.c | 2 | ||||
-rw-r--r-- | g10/gpgv.c | 2 | ||||
-rw-r--r-- | g10/hkp.c | 101 | ||||
-rw-r--r-- | g10/hkp.h | 3 | ||||
-rw-r--r-- | g10/import.c | 191 | ||||
-rw-r--r-- | g10/keyring.c | 28 | ||||
-rw-r--r-- | g10/keyring.o | bin | 56848 -> 57000 bytes | |||
-rw-r--r-- | g10/main.h | 8 | ||||
-rw-r--r-- | g10/mainproc.c | 4 | ||||
-rw-r--r-- | g10/passphrase.c | 138 | ||||
-rw-r--r-- | include/util.h | 3 | ||||
-rw-r--r-- | util/ChangeLog | 15 | ||||
-rw-r--r-- | util/iobuf.c | 56 | ||||
-rw-r--r-- | util/miscutil.c | 13 | ||||
-rw-r--r-- | util/strgutil.c | 29 | ||||
-rw-r--r-- | util/ttyio.c | 2 | ||||
-rw-r--r-- | util/w32reg.c | 69 |
21 files changed, 549 insertions, 157 deletions
@@ -47,6 +47,9 @@ R�mi Guyomarch <[email protected]> Assignment Stefan Bellon <[email protected]> Assignment (All patches to support RISC OS) +Timo Schulz <[email protected]> Assignment + (util/w32reg.c, g10/passphrase.c, g10/hkp.c) + Tedi Heriyanto <[email protected]> Translations [id] Thiago Jung Bauermann <[email protected]> Translations [pt_BR] @@ -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 <[email protected]> + + * 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 <[email protected]> + * 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 <[email protected]> @@ -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; } @@ -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; +} + @@ -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; + + if (!stats) + stats = import_new_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(); + 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 Binary files differindex ff1e2ef62..24f1f0460 100644 --- a/g10/keyring.o +++ b/g10/keyring.o 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 <[email protected]> + + * 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 <[email protected]> * 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,23 +29,13 @@ #include "util.h" #include "memory.h" - -/**************** - * Return a string from the Win32 Registry or NULL in case of - * error. Caller must release the return value. A NUKK for root - * is an alias fro HKEY_CURRENT_USER - * NOTE: The value is allocated with a plain malloc() - use free() and not - * the usual m_free()!!! - */ -char * -read_w32_registry_string( const char *root, const char *dir, const char *name ) +static HKEY +get_root_key(const char *root) { - HKEY root_key, key_handle; - DWORD n1, nbytes; - char *result = NULL; - + HKEY root_key; + if( !root ) - root_key = HKEY_CURRENT_USER; + root_key = HKEY_CURRENT_USER; else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) root_key = HKEY_CLASSES_ROOT; else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) @@ -59,6 +49,27 @@ read_w32_registry_string( const char *root, const char *dir, const char *name ) 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 + * error. Caller must release the return value. A NUKK for root + * is an alias fro HKEY_CURRENT_USER + * NOTE: The value is allocated with a plain malloc() - use free() and not + * the usual m_free()!!! + */ +char * +read_w32_registry_string( const char *root, const char *dir, const char *name ) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes; + char *result = NULL; + + 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__ */ |