added more stuff
authorWerner Koch <wk@gnupg.org>
Fri, 2 Jan 1998 20:40:10 +0000 (20:40 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 2 Jan 1998 20:40:10 +0000 (20:40 +0000)
23 files changed:
README
TODO
cipher/random.c
g10/Makefile.am
g10/Makefile.in
g10/encode.c
g10/filter.h
g10/g10.c
g10/kbnode.c
g10/keydb.h
g10/keyid.c
g10/main.h
g10/mainproc.c
g10/options.h
g10/packet.h
g10/passphrase.c
g10/seckey-cert.c
g10/sign.c
g10/trustdb.c [new file with mode: 0644]
include/util.h
util/iobuf.c
util/logger.c
util/ttyio.c

diff --git a/README b/README
index f166cb7..fa8596b 100644 (file)
--- a/README
+++ b/README
@@ -51,7 +51,6 @@
 
     Key Generation
     --------------
-    Create a key pair with this command:
 
        g10 --gen-key
 
@@ -59,7 +58,7 @@
     good random numbers for prime number generation, it uses a /dev/random
     which will emit only bytes if the kernel can gather enough entropy.
     If you see no progress, you should start some other activities such
-    as mouse moves or a "find /".  Because we have no hardware device
+    as mouse moves or a "find /".  Because we have no hardware device
     to generate random we have to use this method.
 
     Key generation shows progress by printing different characters to
     9) Find a generator for that prime.
 
 
-    Signatures
-    ----------
-    To create a signature, use this:
+    You can sign a key with this command:
+
+       g10 --sign-key Donald
+
+    To sign the key of of "Donald" with your default userid
+
+       g10 --sign-key -u Karl -u Joe Donald
+
+    To sign the key of of "Donald" with the userids of "Karl" and "Joe".
+    All existing signatures are checked, if some are invalid, a menu is
+    offered to delete some of them, and the you are asked for every user
+    wether you want to sign this key.
+
+    You may remove a signature at any time by usiing the option "--edit-sig",
+    which also asks for the sigs to remove.
+
+
+    Sign
+    ----
 
        g10 -s file
 
 
     Creates a signature of file, but writes the output to the file "out".
 
-    Encryption
-    ----------
-    To encrypt data use this:
+
+    Encrypt
+    -------
 
        g10 -e -r heine file
 
     Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
 
 
+    Sign and Encrypt
+    ----------------
+
+       g10 -se -r heine file
+
+    This encrypts files with the public key of "heine" and writes it
+    to "file.g10" after signing it with the default user id.
+
+
+       g10 -se -r heine -u Suttner file
+
+    Ditto, but sign the file with the user id "Suttner"
+
+
+
+    Examine a data or key file
+    --------------------------
+
+       g10 --list-packets datafile
+
+    Use this to list the contents of a data file. If the file is encrypted
+    you are asked for the passphrase, so that G10 is able to look at the
+    inner structure of a encrypted packet.
+
+
+    Batch mode
+    ----------
+    If you use the option "--batch", G10 runs in non-interactive mode and
+    never prompts for input data.  This even does not allow to enter
+    passphrase; until we have a better solution (something like ssh-agent),
+    you can use the option "--passhrase-fd n", which works like PGPs
+    PGPPASSFD.
+
+    Batch mode also causes PGP to terminate as soon as a BAD signature is
+    detected.
+
+
+    Exit status
+    -----------
+    G10 returns with an exit status of 1 if in batch mode and a bad signature
+    has been detected or 2 or higher for all other errors.  You should parse
+    stderr to get detailed informations about the errors.
+
+
+
     Debug Flags
     -----------
     Use the option "--debug n" to output debug informations. This option
     I will run "indent" over the source when making a real distribution,
     but for now I stick to my own formatting rules.
 
-    Compression does not work always; this is the reason that "-z 0"
-    is the default.
-
-    This will be cleaned up of course.
-
     The primary FTP site is "ftp://ftp.guug.de/pub/gcrypt/"
     The primary WWW page is "http://www.d.shuttle.de/isil/g10.html"
 
     Please direct bug reports to <g10-bugs@isil.d.shuttle.de> or better
     post them to the mailing list <g10@net.lut.ac.uk>.
 
-    Have fun
-
-       Werner
 
diff --git a/TODO b/TODO
index 6948e47..41065cf 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,7 +22,6 @@
       before we can check wether we have the pubkey or not.  The one-pass
       signature packets should be implemented to avoid this.
 
-    * compress does not work always!
     * complete cipher/cast.c
     * complete cipher/dsa.c
 
@@ -34,3 +33,5 @@
       of the userid.
       [can be handles in get_pubkey_by_name()]
 
+    * armor has now some problems.
+
index 83efc4b..f865693 100644 (file)
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
 #include <errno.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <fcntl.h>
 #include "util.h"
 #include "cipher.h"
@@ -98,6 +101,7 @@ fill_buffer( byte *buffer, size_t length, int level )
     static int fd_random = -1;
     int fd;
     int n;
+    int warn=0;
 
     if( level == 2 ) {
        if( fd_random == -1 )
@@ -112,11 +116,34 @@ fill_buffer( byte *buffer, size_t length, int level )
 
 
     do {
+       fd_set rfds;
+       struct timeval tv;
+       int rc;
+
+       FD_ZERO(&rfds);
+       FD_SET(fd, &rfds);
+       tv.tv_sec = 3;
+       tv.tv_usec = 0;
+       if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
+           if( !warn )
+               tty_printf(
+"\nNot enough random bytes available.  Please do some other work to give
+the OS a chance to collect more entropy! (Need %d more bytes)\n", length );
+           warn = 1;
+           continue;
+       }
+       else if( rc == -1 ) {
+           tty_printf("select() error: %s\n", strerror(errno));
+           continue;
+       }
+
+       assert( length < 200 );
        do {
            n = read(fd, buffer, length );
        } while( n == -1 && errno == EINTR );
        if( n == -1 )
            log_fatal("read error on random device: %s\n", strerror(errno) );
+       assert( n <= length );
        buffer += n;
        length -= n;
     } while( length );
index 0263990..901370f 100644 (file)
@@ -30,6 +30,7 @@ g10_SOURCES = g10.c           \
              options.h         \
              openfile.c        \
              keyid.c           \
+             trustdb.c         \
              packet.h          \
              parse-packet.c    \
              passphrase.c      \
index 40cf3ae..531b1b8 100644 (file)
@@ -68,6 +68,7 @@ g10_SOURCES = g10.c           \
              options.h         \
              openfile.c        \
              keyid.c           \
+             trustdb.c         \
              packet.h          \
              parse-packet.c    \
              passphrase.c      \
@@ -100,8 +101,8 @@ LINK = $(CC) $(LDFLAGS) -o $@
 g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \
 free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o keygen.o \
 mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \
-openfile.o keyid.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \
-seckey-cert.o seskey.o sign.o comment.o sig-check.o
+openfile.o keyid.o trustdb.o parse-packet.o passphrase.o plaintext.o \
+pubkey-enc.o seckey-cert.o seskey.o sign.o comment.o sig-check.o
 EXTRA_g10_SOURCES =
 g10_LDADD = $(LDADD)
 DIST_COMMON = Makefile.am Makefile.in
@@ -130,7 +131,8 @@ $(srcdir)/.deps/plaintext.P $(srcdir)/.deps/pubkey-enc.P \
 $(srcdir)/.deps/ringedit.P $(srcdir)/.deps/rsa.P \
 $(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \
 $(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P \
-$(srcdir)/.deps/skclist.P $(srcdir)/.deps/textfilter.P
+$(srcdir)/.deps/skclist.P $(srcdir)/.deps/textfilter.P \
+$(srcdir)/.deps/trustdb.P
 SOURCES = $(g10_SOURCES)
 OBJECTS = $(g10_OBJECTS)
 
index b73ee28..b0b148d 100644 (file)
@@ -37,6 +37,7 @@
 
 
 static int encode_simple( const char *filename, int mode );
+static int write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out );
 
 
 
@@ -164,7 +165,7 @@ encode_crypt( const char *filename, STRLIST remusr )
     cipher_filter_context_t cfx;
     armor_filter_context_t afx;
     compress_filter_context_t zfx;
-    PKC_LIST pkc_list, pkc_rover;
+    PKC_LIST pkc_list;
 
     memset( &cfx, 0, sizeof cfx);
     memset( &afx, 0, sizeof afx);
@@ -203,31 +204,9 @@ encode_crypt( const char *filename, STRLIST remusr )
     if( DBG_CIPHER )
        log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
 
-    /* loop over all public key certificates */
-    for( pkc_rover=pkc_list; pkc_rover; pkc_rover = pkc_rover->next ) {
-       PKT_public_cert *pkc;
-       PKT_pubkey_enc  *enc;
-
-       pkc = pkc_rover->pkc;
-       enc = m_alloc_clear( sizeof *enc );
-       enc->pubkey_algo = pkc->pubkey_algo;
-       if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
-           g10_elg_encrypt( pkc, enc, cfx.dek );
-       else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
-           g10_rsa_encrypt( pkc, enc, cfx.dek );
-       else
-           log_bug(NULL);
-       /* and write it */
-       init_packet(&pkt);
-       pkt.pkttype = PKT_PUBKEY_ENC;
-       pkt.pkt.pubkey_enc = enc;
-       rc = build_packet( out, &pkt );
-       free_pubkey_enc(enc);
-       if( rc ) {
-           log_error("build pubkey_enc packet failed: %s\n", g10_errstr(rc) );
-           goto leave;
-       }
-    }
+    rc = write_pubkey_enc_from_list( pkc_list, cfx.dek, out );
+    if( rc  )
+       goto leave;
 
     /* setup the inner packet */
     if( filename ) {
@@ -276,7 +255,6 @@ encode_crypt( const char *filename, STRLIST remusr )
 /****************
  * Filter to do a complete public key encryption.
  */
- #if 0
 int
 encrypt_filter( void *opaque, int control,
               IOBUF a, byte *buf, size_t *ret_len)
@@ -289,6 +267,24 @@ encrypt_filter( void *opaque, int control,
        log_bug(NULL); /* not used */
     }
     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
+       if( !efx->header_okay ) {
+           efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
+           efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
+           make_session_key( efx->cfx.dek );
+           if( DBG_CIPHER )
+               log_hexdump("DEK is: ",
+                            efx->cfx.dek->key, efx->cfx.dek->keylen );
+
+           rc = write_pubkey_enc_from_list( efx->pkc_list, efx->cfx.dek, a );
+           if( rc )
+               return rc;
+
+           iobuf_push_filter( a, cipher_filter, &efx->cfx );
+
+           efx->header_okay = 1;
+       }
+       rc = iobuf_write( a, buf, size );
+
     }
     else if( control == IOBUFCTRL_FREE ) {
     }
@@ -297,5 +293,41 @@ encrypt_filter( void *opaque, int control,
     }
     return rc;
 }
-  #endif
+
+
+/****************
+ * Write pubkey-enc packets from the list of PKCs to OUT.
+ */
+static int
+write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out )
+{
+    PACKET pkt;
+    PKT_public_cert *pkc;
+    PKT_pubkey_enc  *enc;
+    int rc;
+
+    for( ; pkc_list; pkc_list = pkc_list->next ) {
+
+       pkc = pkc_list->pkc;
+       enc = m_alloc_clear( sizeof *enc );
+       enc->pubkey_algo = pkc->pubkey_algo;
+       if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
+           g10_elg_encrypt( pkc, enc, dek );
+       else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
+           g10_rsa_encrypt( pkc, enc, dek );
+       else
+           log_bug(NULL);
+       /* and write it */
+       init_packet(&pkt);
+       pkt.pkttype = PKT_PUBKEY_ENC;
+       pkt.pkt.pubkey_enc = enc;
+       rc = build_packet( out, &pkt );
+       free_pubkey_enc(enc);
+       if( rc ) {
+           log_error("build pubkey_enc packet failed: %s\n", g10_errstr(rc) );
+           return rc;
+       }
+    }
+    return 0;
+}
 
index 11c05e4..83ed3d1 100644 (file)
@@ -65,6 +65,7 @@ typedef struct {
 } cipher_filter_context_t;
 
 
+
 typedef struct {
     size_t linesize;
     byte *line;
@@ -73,6 +74,9 @@ typedef struct {
     int eof;
 } text_filter_context_t;
 
+
+/* encrypt_filter_context_t defined in main.h */
+
 /*-- mdfilter.c --*/
 int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
 void free_md_filter_context( md_filter_context_t *mfx );
index 1df8008..45fc6b6 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -121,7 +121,7 @@ main( int argc, char **argv )
     { 'e', "encrypt",   0, "encrypt data" },
     { 'd', "decrypt",   0, "decrypt data (default)" },
   /*{ 'c', "check",     0, "check a signature (default)" }, */
-    { 'l', "local-user",2, "use this user-id to sign or decrypt" },
+    { 'u', "local-user",2, "use this user-id to sign or decrypt" },
     { 'r', "remote-user", 2, "use this user-id for encryption" },
     { 510, "debug"     ,4|16, "set debugging flags" },
     { 511, "debug-all" ,0, "enable full debugging"},
@@ -135,13 +135,17 @@ main( int argc, char **argv )
     { 518, "options"   , 2, "read options from file" },
     { 519, "no-armor",   0, "\r"},
     { 520, "no-default-keyring", 0, "\r" },
+    { 521, "list-packets",0,"list only the sequence of packets"},
+    { 522, "no-greeting", 0, "\r" },
+    { 523, "passphrase-fd",1, "\r" },
+    { 524, "edit-sig"  ,0, "edit a key signature" },
 
     {0} };
     ARGPARSE_ARGS pargs;
     IOBUF a;
     int rc;
     enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
-          aTest, aPrintMDs, aSignKey, aClearsig
+          aTest, aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig,
     } action = aNull;
     int orig_argc;
     char **orig_argv;
@@ -158,9 +162,10 @@ main( int argc, char **argv )
     int default_config =1;
     int errors=0;
     int default_keyring = 1;
+    int greeting = 1;
 
 
-    opt.compress = 0; /* defaults to no compression level */
+    opt.compress = -1; /* defaults to standard compress level */
 
     /* check wether we have a config file on the commandline */
     orig_argc = argc;
@@ -221,7 +226,7 @@ main( int argc, char **argv )
               /* fall trough */
          case 's': action = action == aEncr? aSignEncr : aSign;  break;
          case 't': action = aClearsig;  break;
-         case 'l': /* store the local users */
+         case 'u': /* store the local users */
            sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
            strcpy(sl->d, pargs.r.ret_str);
            sl->next = locusr;
@@ -233,7 +238,7 @@ main( int argc, char **argv )
            sl->next = remusr;
            remusr = sl;
            break;
-         case 500: opt.batch = 1; break;
+         case 500: opt.batch = 1; greeting = 0; break;
          case 501: opt.answer_yes = 1; break;
          case 502: opt.answer_no = 1; break;
          case 503: action = aKeygen; break;
@@ -259,6 +264,10 @@ main( int argc, char **argv )
            break;
          case 519: opt.no_armor=1; opt.armor=0; break;
          case 520: default_keyring = 0; break;
+         case 521: action = aListPackets; break;
+         case 522: greeting = 0; break;
+         case 523: set_passphrase_fd( pargs.r.ret_int ); break;
+         case 524: action = aEditSig; break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
@@ -275,11 +284,11 @@ main( int argc, char **argv )
     set_debug();
     if( opt.verbose > 1 )
        set_packet_list_mode(1);
-    if( opt.verbose && isatty(fileno(stdin)) ) {
+    if( greeting ) {
        if( *(s=strusage(10))  )
-           fputs(s, stderr);
+           tty_printf("%s", s);
        if( *(s=strusage(30))  )
-           fputs(s, stderr);
+           tty_printf("%s", s);
     }
 
     if( !sec_nrings || default_keyring ) { /* add default secret rings */
@@ -347,6 +356,14 @@ main( int argc, char **argv )
            log_error("sign_key('%s'): %s\n", fname_print, g10_errstr(rc) );
        break;
 
+      case aEditSig: /* Edit a key signature */
+       if( argc != 1 )
+           usage(1);
+       /* note: fname is the user id! */
+       if( (rc = edit_keysigs(fname)) )
+           log_error("edit_keysig('%s'): %s\n", fname_print, g10_errstr(rc) );
+       break;
+
 
       case aPrimegen:
        if( argc == 1 ) {
@@ -388,6 +405,8 @@ main( int argc, char **argv )
 
       case aTest: do_test( argc? atoi(*argv): 0 ); break;
 
+      case aListPackets:
+       opt.list_packets=1;
       default:
        if( argc > 1 )
            usage(1);
@@ -398,6 +417,10 @@ main( int argc, char **argv )
            memset( &afx, 0, sizeof afx);
            iobuf_push_filter( a, armor_filter, &afx );
        }
+       if( action == aListPackets ) {
+           set_packet_list_mode(1);
+           opt.list_packets=1;
+       }
        proc_packets( a );
        iobuf_close(a);
        break;
@@ -406,7 +429,7 @@ main( int argc, char **argv )
     /* cleanup */
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
-    return 0;
+    return log_get_errorcount(0)? 2:0;
 }
 
 
@@ -509,33 +532,5 @@ do_test(int times)
 
     m_check(NULL);
   #endif
-  #if 0
-    char *array;
-    int i, j;
-    int n = 6;
-    int m = times;
-
-    if( m > n )
-       abort();
-    array = m_alloc_clear( n );
-    memset( array, 1, m );
-
-    for(i=0;; i++) {
-       printf("i=%3d: ", i );
-       for(j=0; j < n ; j++ )
-           if( array[j] )
-               putchar( 'X' );
-           else
-               putchar( '-' );
-       putchar('\n');
-       m_out_of_n( array, m, n );
-       for(j=0; j < n; j++ )
-           if( !array[j] )
-               break;
-       if( j == m )
-           break;
-    }
-  #endif
 }
 
-
index 844bafe..19e0870 100644 (file)
@@ -38,6 +38,7 @@ new_kbnode( PACKET *pkt )
     n->pkt = pkt;
     n->child = NULL;
     n->flag = 0;
+    n->private_flag=0; /* kludge to delete a node */
     return n;
 }
 
@@ -58,6 +59,16 @@ release_kbnode( KBNODE n )
 
 
 /****************
+ * Delete NODE from ROOT, ROOT must exist!
+ * Note does only work with walk_kbtree!!
+ */
+void
+delete_kbnode( KBNODE root, KBNODE node )
+{
+    node->private_flag |= 1;
+}
+
+/****************
  * Append NODE to ROOT, ROOT must exist!
  */
 void
@@ -116,26 +127,35 @@ find_kbparent( KBNODE root, KBNODE node )
 KBNODE
 walk_kbtree( KBNODE root, KBNODE *context )
 {
+    return walk_kbtree2( root, context, 0 );
+}
+
+KBNODE
+walk_kbtree2( KBNODE root, KBNODE *context, int all )
+{
     KBNODE n;
 
-    if( !*context ) {
-       *context = root;
-       return root;
-    }
+    do {
+       if( !*context ) {
+           *context = root;
+           return root;
+       }
+
+       n = *context;
+       if( n->child ) {
+           n = n->child;
+           *context = n;
+       }
+       else if( n->next ) {
+           n = n->next;
+           *context = n;
+       }
+       else if( (n = find_kbparent( root, n )) ) {
+           n = n->next;
+           *context = n;
+       }
+    } while( !all && n && (n->private_flag & 1) );
 
-    n = *context;
-    if( n->child ) {
-       n = n->child;
-       *context = n;
-    }
-    else if( n->next ) {
-       n = n->next;
-       *context = n;
-    }
-    else if( (n = find_kbparent( root, n )) ) {
-       n = n->next;
-       *context = n;
-    }
     return n;
 }
 
@@ -147,3 +167,4 @@ clear_kbnode_flags( KBNODE n )
        n->flag = 0;
     }
 }
+
index f0d8b51..cbca04c 100644 (file)
@@ -41,6 +41,7 @@ struct kbnode_struct {
     KBNODE next;   /* used to form a link list */
     KBNODE child;
     int flag;
+    int private_flag;
 };
 
 /****************
@@ -81,6 +82,8 @@ void release_skc_list( SKC_LIST skc_list );
 int  build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock );
 
 /*-- passphrase.h --*/
+void set_passphrase_fd( int fd );
+int  get_passphrase_fd(void);
 DEK *get_passphrase_hash( u32 *keyid, char *text );
 int make_dek_from_passphrase( DEK *dek, int mode );
 
@@ -112,10 +115,12 @@ byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
 /*-- kbnode.c --*/
 KBNODE new_kbnode( PACKET *pkt );
 void release_kbnode( KBNODE n );
+void delete_kbnode( KBNODE root, KBNODE node );
 void add_kbnode( KBNODE root, KBNODE node );
 void add_kbnode_as_child( KBNODE root, KBNODE node );
 KBNODE find_kbparent( KBNODE root, KBNODE node );
 KBNODE walk_kbtree( KBNODE root, KBNODE *context );
+KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all );
 void clear_kbnode_flags( KBNODE n );
 
 /*-- ringedit.c --*/
index 307e28c..5848459 100644 (file)
@@ -155,7 +155,7 @@ datestr_from_pkc( PKT_public_cert *pkc )
     time_t atime = pkc->timestamp;
 
     tp = gmtime( &atime );
-    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
+    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
     return buffer;
 }
 
@@ -167,7 +167,7 @@ datestr_from_skc( PKT_secret_cert *skc )
     time_t atime = skc->timestamp;
 
     tp = gmtime( &atime );
-    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
+    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
     return buffer;
 }
 
@@ -179,7 +179,7 @@ datestr_from_sig( PKT_signature *sig )
     time_t atime = sig->timestamp;
 
     tp = gmtime( &atime );
-    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday );
+    sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
     return buffer;
 }
 
index 0d00dd1..15caaab 100644 (file)
 #define DEFAULT_PUBKEY_ALGO  PUBKEY_ALGO_ELGAMAL
 #define DEFAULT_DIGEST_ALGO  DIGEST_ALGO_RMD160
 
+
+typedef struct {
+    int header_okay;
+    PKC_LIST pkc_list;
+    cipher_filter_context_t cfx;
+} encrypt_filter_context_t;
+
+
 /*-- encode.c --*/
 int encode_symmetric( const char *filename );
 int encode_store( const char *filename );
 int encode_crypt( const char *filename, STRLIST remusr );
+int encrypt_filter( void *opaque, int control,
+                   IOBUF a, byte *buf, size_t *ret_len);
+
 
 /*-- sign.c --*/
 int sign_file( const char *filename, int detached, STRLIST locusr,
               int encrypt, STRLIST remusr );
 int sign_key( const char *username, STRLIST locusr );
+int edit_keysigs( const char *username );
 
 /*-- sig-check.c --*/
 int check_key_signature( KBNODE root, KBNODE node );
index 338ce3d..b46cb13 100644 (file)
@@ -46,7 +46,6 @@ typedef struct {
     md_filter_context_t mfx;
     DEK *dek;
     int last_was_pubkey_enc;
-    int opt_list;
     KBNODE cert;     /* the current certificate */
     int have_data;
     IOBUF iobuf;    /* used to get the filename etc. */
@@ -198,7 +197,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
 
     c->last_was_pubkey_enc = 1;
     enc = pkt->pkt.pubkey_enc;
-    printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );
+    /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
     if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
        || enc->pubkey_algo == PUBKEY_ALGO_RSA  ) {
        m_free(c->dek ); /* paranoid: delete a pending DEK */
@@ -213,11 +212,12 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
 
     if( result == -1 )
        ;
-    else if( !result )
-       fputs(  "     DEK is good", stdout );
+    else if( !result ) {
+       if( opt.verbose > 1 )
+           log_info( "pubkey_enc packet: Good DEK\n" );
+    }
     else
-       printf( "     %s", g10_errstr(result));
-    putchar('\n');
+       log_error( "pubkey_enc packet: %s\n", g10_errstr(result));
     free_packet(pkt);
 }
 
@@ -228,7 +228,7 @@ proc_encrypted( CTX c, PACKET *pkt )
 {
     int result = 0;
 
-    printf("dat: %sencrypted data\n", c->dek?"":"conventional ");
+    /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
     if( !c->dek && !c->last_was_pubkey_enc ) {
        /* assume this is conventional encrypted data */
        c->dek = m_alloc_secure( sizeof *c->dek );
@@ -242,11 +242,13 @@ proc_encrypted( CTX c, PACKET *pkt )
     m_free(c->dek); c->dek = NULL;
     if( result == -1 )
        ;
-    else if( !result )
-       fputs(  "     encryption okay",stdout);
-    else
-       printf( "     %s", g10_errstr(result));
-    putchar('\n');
+    else if( !result ) {
+       if( opt.verbose > 1 )
+           log_info("encryption okay\n");
+    }
+    else {
+       log_error("encryption failed: %s\n", g10_errstr(result));
+    }
     free_packet(pkt);
     c->last_was_pubkey_enc = 0;
 }
@@ -256,9 +258,10 @@ static void
 proc_plaintext( CTX c, PACKET *pkt )
 {
     PKT_plaintext *pt = pkt->pkt.plaintext;
-    int result;
+    int rc;
 
-    printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
+    if( opt.verbose )
+       log_info("original file name='%.*s'\n", pt->namelen, pt->name);
     free_md_filter_context( &c->mfx );
     /* fixme: take the digest algo(s) to use from the
      * onepass_sig packet (if we have these)
@@ -266,12 +269,9 @@ proc_plaintext( CTX c, PACKET *pkt )
      * textmode filter (sigclass 0x01)
      */
     c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
-    result = handle_plaintext( pt, &c->mfx );
-    if( !result )
-       fputs(  "     okay", stdout);
-    else
-       printf( "     %s", g10_errstr(result));
-    putchar('\n');
+    rc = handle_plaintext( pt, &c->mfx );
+    if( rc )
+       log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
     free_packet(pkt);
     c->last_was_pubkey_enc = 0;
 }
@@ -281,15 +281,12 @@ static void
 proc_compressed( CTX c, PACKET *pkt )
 {
     PKT_compressed *zd = pkt->pkt.compressed;
-    int result;
+    int rc;
 
-    printf("zip: compressed data packet\n");
-    result = handle_compressed( zd );
-    if( !result )
-       fputs(  "     okay", stdout);
-    else
-       printf( "     %s", g10_errstr(result));
-    putchar('\n');
+    /*printf("zip: compressed data packet\n");*/
+    rc = handle_compressed( zd );
+    if( rc )
+       log_error("uncompressing failed: %s\n", g10_errstr(rc));
     free_packet(pkt);
     c->last_was_pubkey_enc = 0;
 }
@@ -505,7 +502,6 @@ proc_packets( IOBUF a )
     u32 keyid[2];
     int newpkt;
 
-    c->opt_list = 1;
     c->iobuf = a;
     init_packet(pkt);
     while( (rc=parse_packet(a, pkt)) != -1 ) {
@@ -522,17 +518,27 @@ proc_packets( IOBUF a )
            continue;
        }
        newpkt = -1;
-       switch( pkt->pkttype ) {
-         case PKT_PUBLIC_CERT: newpkt = add_public_cert( c, pkt ); break;
-         case PKT_SECRET_CERT: newpkt = add_secret_cert( c, pkt ); break;
-         case PKT_USER_ID:     newpkt = add_user_id( c, pkt ); break;
-         case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
-         case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
-         case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
-         case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
-         case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
-         case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
-         default: newpkt = 0; break;
+       if( opt.list_packets ) {
+           switch( pkt->pkttype ) {
+             case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
+             case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
+             case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+             default: newpkt = 0; break;
+           }
+       }
+       else {
+           switch( pkt->pkttype ) {
+             case PKT_PUBLIC_CERT: newpkt = add_public_cert( c, pkt ); break;
+             case PKT_SECRET_CERT: newpkt = add_secret_cert( c, pkt ); break;
+             case PKT_USER_ID:     newpkt = add_user_id( c, pkt ); break;
+             case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
+             case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
+             case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
+             case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
+             case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+             case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
+             default: newpkt = 0; break;
+           }
        }
        if( pkt->pkttype != PKT_SIGNATURE )
            c->have_data = pkt->pkttype == PKT_PLAINTEXT;
@@ -575,13 +581,16 @@ proc_tree( CTX c, KBNODE node )
     KBNODE n1;
     int rc;
 
+    if( opt.list_packets )
+       return;
+
     if( node->pkt->pkttype == PKT_PUBLIC_CERT )
        list_node( c, node );
     else if( node->pkt->pkttype == PKT_SECRET_CERT )
        list_node( c, node );
     else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
        if( !node->child )
-           log_error("proc_tree: onepass_sig without followin data\n");
+           log_error("proc_tree: onepass_sig without data\n");
        else if( node->child->pkt->pkttype != PKT_SIGNATURE )
            log_error("proc_tree: onepass_sig not followed by signature\n");
        else {  /* check all signatures */
@@ -611,6 +620,8 @@ proc_tree( CTX c, KBNODE node )
                    log_error("BAD signature from ");
                    print_keyid( stderr, sig->keyid );
                    putc('\n', stderr);
+                   if( opt.batch )
+                       exit(1);
                }
                else
                    log_error("Can't check signature made by %08lX: %s\n",
index c1aea3f..31aa955 100644 (file)
@@ -35,7 +35,7 @@ struct {
     int fingerprint; /* list fingerprints */
     int list_sigs;   /* list signatures */
     int no_armor;
-    int reserved5;
+    int list_packets; /* list-packets mode */
     int reserved6;
     int reserved7;
     int reserved8;
index f7dbf97..4a5a5a3 100644 (file)
@@ -210,6 +210,7 @@ struct packet_struct {
 
 /*-- mainproc.c --*/
 int proc_packets( IOBUF a );
+int list_packets( IOBUF a );
 
 /*-- parse-packet.c --*/
 int set_packet_list_mode( int mode );
index a974ca9..df8ac71 100644 (file)
 #include <assert.h>
 #include "util.h"
 #include "memory.h"
+#include "options.h"
 #include "ttyio.h"
 #include "cipher.h"
 #include "keydb.h"
 
+static int pwfd = -1;
 
 static int hash_passphrase( DEK *dek, char *pw );
 
+void
+set_passphrase_fd( int fd )
+{
+    pwfd = fd;
+}
+
+int
+get_passphrase_fd()
+{
+    return pwfd;
+}
+
 
 /****************
  * Get a passphrase for the secret key with KEYID, display TEXT
@@ -41,35 +55,51 @@ static int hash_passphrase( DEK *dek, char *pw );
 DEK *
 get_passphrase_hash( u32 *keyid, char *text )
 {
-    char *p=NULL, *pw;
+    char *pw;
     DEK *dek;
 
-    if( keyid ) {
+    if( keyid && !opt.batch ) {
        char *ustr;
-       tty_printf("\nNeed a pass phrase to unlock the secret key!\n");
-       tty_printf("KeyID: " );
+       tty_printf("Need a pass phrase to unlock the secret key for:\n");
+       tty_printf("  \"" );
        ustr = get_user_id_string( keyid );
        tty_print_string( ustr, strlen(ustr) );
        m_free(ustr);
-       tty_printf("\n\n");
+       tty_printf("\"\n\n");
 
     }
-    if( keyid && (p=getenv("G10PASSPHRASE")) ) {
-       pw = m_alloc_secure(strlen(p)+1);
-       strcpy(pw,p);
-       tty_printf("Taking it from $G10PASSPHRASE !\n",  keyid[1] );
+    if( pwfd != -1 ) { /* read the passphrase from the given descriptor */
+       int i, len;
+
+       if( !opt.batch )
+           tty_printf("Reading from file descriptor %d ...", pwfd );
+       for( pw = NULL, i = len = 100; ; i++ ) {
+           if( i >= len-1 ) {
+               char *pw2 = pw;
+               len += 100;
+               pw = m_alloc_secure( len );
+               if( pw2 )
+                   memcpy(pw, pw2, i );
+               i=0;
+           }
+           if( read( pwfd, pw+i, 1) != 1 || pw[i] == '\n' )
+               break;
+       }
+       pw[i] = 0;
+       if( !opt.batch )
+           tty_printf("\b\b\b   \n" );
     }
-    else
+    else if( opt.batch )
+       log_fatal("Can't query password in batchmode\n");
+    else {
        pw = tty_get_hidden("Enter pass phrase: " );
+       tty_kill_prompt();
+    }
     dek = m_alloc_secure( sizeof *dek );
     dek->algo = CIPHER_ALGO_BLOWFISH;
     if( hash_passphrase( dek, pw ) )
        log_bug("get_passphrase_hash\n");
     m_free(pw); /* is allocated in secure memory, so it will be burned */
-    if( !p ) {
-       tty_kill_prompt();
-       tty_printf("\n");
-    }
     return dek;
 }
 
@@ -89,6 +119,7 @@ make_dek_from_passphrase( DEK *dek, int mode )
     tty_kill_prompt();
     if( mode == 2 ) {
        pw2 = tty_get_hidden("Repeat pass phrase: " );
+       tty_kill_prompt();
        if( strcmp(pw, pw2) ) {
            m_free(pw2);
            m_free(pw);
index 85d93b4..c1ea596 100644 (file)
@@ -65,6 +65,7 @@ check_elg( PKT_secret_cert *cert )
     unsigned nbytes;
     u32 keyid[2];
     ELG_secret_key skey;
+    char save_iv[8];
 
     if( cert->d.elg.is_protected ) { /* remove the protection */
        DEK *dek = NULL;
@@ -80,6 +81,7 @@ check_elg( PKT_secret_cert *cert )
            blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
            m_free(dek); /* pw is in secure memory, so m_free() burns it */
            blowfish_setiv( blowfish_ctx, NULL );
+           memcpy(save_iv, cert->d.elg.protect.blowfish.iv, 8 );
            blowfish_decode_cfb( blowfish_ctx,
                                 cert->d.elg.protect.blowfish.iv,
                                 cert->d.elg.protect.blowfish.iv, 8 );
@@ -94,6 +96,7 @@ check_elg( PKT_secret_cert *cert )
            /* now let's see wether we have used the right passphrase */
            if( csum != cert->d.elg.csum ) {
                mpi_free(test_x);
+               memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 );
                return G10ERR_BAD_PASS;
            }
 
@@ -105,6 +108,7 @@ check_elg( PKT_secret_cert *cert )
            memset( &skey, 0, sizeof skey );
            if( !res ) {
                mpi_free(test_x);
+               memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 );
                return G10ERR_BAD_PASS;
            }
            mpi_set(cert->d.elg.x, test_x);
@@ -274,6 +278,8 @@ check_secret_key( PKT_secret_cert *cert )
       #endif
        else
            rc = G10ERR_PUBKEY_ALGO;
+       if( get_passphrase_fd() != -1 )
+           break;
     }
     return rc;
 }
index 67e229f..a854139 100644 (file)
@@ -79,6 +79,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
     compress_filter_context_t zfx;
     md_filter_context_t mfx;
     text_filter_context_t tfx;
+    encrypt_filter_context_t efx;
     IOBUF inp = NULL, out = NULL;
     PACKET pkt;
     PKT_plaintext *pt = NULL;
@@ -92,6 +93,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
     memset( &zfx, 0, sizeof zfx);
     memset( &mfx, 0, sizeof mfx);
     memset( &tfx, 0, sizeof tfx);
+    memset( &efx, 0, sizeof efx);
     init_packet( &pkt );
 
     if( (rc=build_skc_list( locusr, &skc_list, 1 )) )
@@ -127,8 +129,9 @@ sign_file( const char *filename, int detached, STRLIST locusr,
        iobuf_push_filter( out, compress_filter, &zfx );
 
     if( encrypt ) {
-       /* prepare for encryption */
-       /* FIXME!!!!!!! */
+       efx.pkc_list = pkc_list;
+       /* fixme: set efx.cfx.datalen if known */
+       iobuf_push_filter( out, encrypt_filter, &efx );
     }
 
     /* loop over the secret certificates and build headers */
@@ -348,7 +351,15 @@ sign_it_p( PKT_public_cert *pkc, PKT_user_id *uid )
 }
 
 
-static void
+/****************
+ * Check the keysigs and set the flags to indicate errors.
+ * Usage of nodes flag bits:
+ * Bit 0 = bad signature
+ *     1 = no public key
+ *     2 = other error
+ * Returns true if error found.
+ */
+static int
 check_all_keysigs( KBNODE keyblock )
 {
     KBNODE kbctx;
@@ -384,6 +395,7 @@ check_all_keysigs( KBNODE keyblock )
                m_free(p);
            }
            tty_printf("\n");
+           /* FIXME: update the trustdb */
        }
     }
     if( inv_sigs )
@@ -392,6 +404,76 @@ check_all_keysigs( KBNODE keyblock )
        tty_printf("No public key for %d signatures\n", no_key );
     if( oth_err )
        tty_printf("%d signatures not checked due to errors\n", oth_err );
+    return inv_sigs || no_key || oth_err;
+}
+
+
+/****************
+ * Ask and remove invalid signatures are to be removed.
+ */
+static int
+remove_keysigs( KBNODE keyblock, int all )
+{
+    KBNODE kbctx;
+    KBNODE node;
+    char *answer;
+    int yes;
+    int count;
+
+    count = 0;
+    for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
+       if( ((node->flag & 7) || all )
+           && node->pkt->pkttype == PKT_SIGNATURE
+           && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
+           PKT_signature *sig = node->pkt->pkt.signature;
+           int sigrc;
+
+           if( all ) {
+               /* fixme: skip self-sig */
+           }
+
+           tty_printf("\n \"%08lX %s   ",
+                       sig->keyid[1], datestr_from_sig(sig));
+           if( node->flag & 6 )
+               tty_printf("[User name not available] ");
+           else {
+               size_t n;
+               char *p = get_user_id( sig->keyid, &n );
+               tty_print_string( p, n );
+               m_free(p);
+           }
+           tty_printf("\"\n");
+           if( node->flag & 1 )
+               tty_printf("This is a BAD signature!\n");
+           else if( node->flag & 2 )
+               tty_printf("Public key not available.\n");
+           else if( node->flag & 4 )
+               tty_printf("The signature could not be checked!\n");
+           answer = tty_get("\nRemove this signature? ");
+           tty_kill_prompt();
+           if( answer_is_yes(answer) ) {
+               node->flag |= 128;     /* use bit 7 to mark this node */
+               count++;
+           }
+           m_free(answer);
+       }
+    }
+
+    if( !count )
+       return 0; /* nothing to remove */
+    answer = tty_get("Do you really want to remove the selected signatures? ");
+    tty_kill_prompt();
+    yes = answer_is_yes(answer);
+    m_free(answer);
+    if( !yes )
+       return 0;
+
+    for( kbctx=NULL; (node=walk_kbtree2( keyblock, &kbctx, 1)) ; ) {
+       if( node->flag & 128)
+           delete_kbnode( keyblock, node );
+    }
+
+    return 1;
 }
 
 
@@ -414,6 +496,7 @@ sign_key( const char *username, STRLIST locusr )
     PKT_public_cert *pkc;
     int any;
     u32 pkc_keyid[2];
+    char *answer;
 
     memset( &mfx, 0, sizeof mfx);
 
@@ -464,9 +547,16 @@ sign_key( const char *username, STRLIST locusr )
     }
 
     clear_kbnode_flags( keyblock );
-    check_all_keysigs( keyblock );
-    /* look wether we should ask to remove invalid keys */
-    /*+ FIXME: */
+    if( check_all_keysigs( keyblock ) ) {
+       if( !opt.batch ) {
+           /* ask wether we really should do anything */
+           answer = tty_get("To you want to remove some of the invalid sigs? ");
+           tty_kill_prompt();
+           if( answer_is_yes(answer) )
+               remove_keysigs( keyblock, 0 );
+           m_free(answer);
+       }
+    }
 
     /* check wether we have already signed it */
     for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
@@ -524,7 +614,7 @@ sign_key( const char *username, STRLIST locusr )
 
     rc = update_keyblock( &kbpos, keyblock );
     if( rc ) {
-       log_error("insert_keyblock failed: %s\n", g10_errstr(rc) );
+       log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
        goto leave;
     }
 
@@ -537,6 +627,75 @@ sign_key( const char *username, STRLIST locusr )
 
 
 
+int
+edit_keysigs( const char *username )
+{
+    int rc = 0;
+    KBNODE keyblock = NULL;
+    KBNODE kbctx, node;
+    KBPOS kbpos;
+    PKT_public_cert *pkc;
+    int any;
+    u32 pkc_keyid[2];
+    char *answer;
+
+    /* search the userid */
+    rc = search_keyblock_byname( &kbpos, username );
+    if( rc ) {
+       log_error("user '%s' not found\n", username );
+       goto leave;
+    }
+
+    /* read the keyblock */
+    rc = read_keyblock( &kbpos, &keyblock );
+    if( rc ) {
+       log_error("error reading the certificate: %s\n", g10_errstr(rc) );
+       goto leave;
+    }
+
+    /* get the keyid from the keyblock */
+    for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
+       if( node->pkt->pkttype == PKT_PUBLIC_CERT )
+           break;
+    }
+    if( !node ) {
+       log_error("Oops; public key not found anymore!\n");
+       rc = G10ERR_GENERAL;
+       goto leave;
+    }
+
+    pkc = node->pkt->pkt.public_cert;
+    keyid_from_pkc( pkc, pkc_keyid );
+    log_info("Checking signatures of this public key certificate:\n");
+    tty_printf("pub  %4u%c/%08lX %s   ",
+             nbits_from_pkc( pkc ),
+             pubkey_letter( pkc->pubkey_algo ),
+             pkc_keyid[1], datestr_from_pkc(pkc) );
+    {
+       size_t n;
+       char *p = get_user_id( pkc_keyid, &n );
+       tty_print_string( p, n > 40? 40 : n );
+       m_free(p);
+       tty_printf("\n");
+    }
+
+    clear_kbnode_flags( keyblock );
+    check_all_keysigs( keyblock );
+    if( remove_keysigs( keyblock, 1 ) ) {
+       rc = update_keyblock( &kbpos, keyblock );
+       if( rc ) {
+           log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
+           goto leave;
+       }
+    }
+
+  leave:
+    release_kbnode( keyblock );
+    return rc;
+}
+
+
+
 /****************
  * Create a signature packet for the given public key certificate
  * and the user id and return it in ret_sig. User signature class SIGCLASS
diff --git a/g10/trustdb.c b/g10/trustdb.c
new file mode 100644 (file)
index 0000000..00774f5
--- /dev/null
@@ -0,0 +1,35 @@
+/* trustdb.c
+ *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *
+ * This file is part of G10.
+ *
+ * G10 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * G10 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "errors.h"
+#include "iobuf.h"
+#include "keydb.h"
+#include "memory.h"
+#include "util.h"
+
+
+
index 6a07fcb..c32f74a 100644 (file)
@@ -56,7 +56,8 @@ typedef struct {
 } ARGPARSE_OPTS;
 
 /*-- logger.c --*/
-void set_log_pid( int pid );
+void log_set_pid( int pid );
+int  log_get_errorcount( int clear );
 void printstr( int level, const char *fmt, ... );
 void log_bug( const char *fmt, ... );
 void log_fatal( const char *fmt, ... );
index 58b0d77..981fb2e 100644 (file)
@@ -450,6 +450,7 @@ iobuf_push_filter( IOBUF a,
     /* remove the filter stuff from the new stream */
     a->filter = NULL;
     a->filter_ov = NULL;
+    a->filter_eof = 0;
     if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
        b->d.buf = m_alloc( a->d.size );
        b->d.len = 0;
@@ -539,7 +540,7 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
        m_free(b);
     }
     else if( !b->chain ) { /* remove the last iobuf from the chain */
-       log_bug("Ohh jeee, trying to a head filter\n");
+       log_bug("Ohh jeee, trying to remove a head filter\n");
     }
     else {  /* remove an intermediate iobuf from the chain */
        log_bug("Ohh jeee, trying to remove an intermediate filter\n");
@@ -833,13 +834,13 @@ iobuf_set_block_mode( IOBUF a, size_t n )
 
 
 /****************
- * checks wether the stream is in block mode
+ * Checks wether the stream is in block mode
+ * Note: This does not work if other filters are pushed on the stream.
  */
 int
 iobuf_in_block_mode( IOBUF a )
 {
-    for(; a; a = a->chain )
-       if( a->filter == block_filter )
+    if( a && a->filter == block_filter )
            return 1; /* yes */
     return 0; /* no */
 }
index 8993ba4..c32332b 100644 (file)
 #include "util.h"
 
 static char pidstring[15];
-
+static int errorcount;
 
 void
-set_log_pid( int pid )
+log_set_pid( int pid )
 {
     if( pid )
        sprintf(pidstring,"[%u]", (unsigned)pid );
@@ -37,6 +37,15 @@ set_log_pid( int pid )
        *pidstring = 0;
 }
 
+int
+log_get_errorcount( int clear)
+{
+    int n = errorcount;
+    if( clear )
+       errorcount = 0;
+    return n;
+}
+
 
 /****************
  * General interface for printing a line
@@ -90,6 +99,7 @@ log_error( const char *fmt, ... )
     va_start( arg_ptr, fmt ) ;
     vfprintf(stderr,fmt,arg_ptr) ;
     va_end(arg_ptr);
+    errorcount++;
 }
 
 void
index c8a4e8f..31b80e6 100644 (file)
 #include "memory.h"
 #include "ttyio.h"
 
+static FILE *ttyfp = NULL;
 static int last_prompt_len;
 
-static FILE *
-open_tty(struct termios *termsave )
+static void
+init_ttyfp()
 {
-    struct termios term;
+    if( ttyfp )
+       return;
 
-    FILE *tty = fopen("/dev/tty", "r");
-    if( !tty )
+    ttyfp = fopen("/dev/tty", "r+");
+    if( !ttyfp )
        log_fatal("cannot open /dev/tty: %s\n", strerror(errno) );
-
-    if( termsave ) { /* hide input */
-       if( tcgetattr(fileno(tty), termsave) )
-           log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
-       term = *termsave;
-       term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
-       if( tcsetattr( fileno(tty), TCSAFLUSH, &term ) )
-           log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
-    }
-
-
-    return tty;
-}
-
-static void
-close_tty( FILE *tty, struct termios *termsave )
-{
-    if( termsave ) {
-       if( tcsetattr(fileno(tty), TCSAFLUSH, termsave) )
-           log_error("tcsetattr() failed: %s\n", strerror(errno) );
-       putc('\n', stderr);
-    }
-    fclose(tty);
 }
 
 
-
 void
 tty_printf( const char *fmt, ... )
 {
     va_list arg_ptr;
 
+    if( !ttyfp )
+       init_ttyfp();
+
     va_start( arg_ptr, fmt ) ;
-    last_prompt_len += vfprintf(stderr,fmt,arg_ptr) ;
+    last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
     va_end(arg_ptr);
-    fflush(stderr);
+    fflush(ttyfp);
 }
 
 
@@ -85,18 +66,21 @@ tty_printf( const char *fmt, ... )
 void
 tty_print_string( byte *p, size_t n )
 {
+    if( !ttyfp )
+       init_ttyfp();
+
     for( ; n; n--, p++ )
        if( iscntrl( *p ) ) {
-           putc('\\', stderr);
+           putc('\\', ttyfp);
            if( *p == '\n' )
-               putc('n', stderr);
+               putc('n', ttyfp);
            else if( !*p )
-               putc('0', stderr);
+               putc('0', ttyfp);
            else
-               fprintf(stderr, "x%02x", *p );
+               fprintf(ttyfp, "x%02x", *p );
        }
        else
-           putc(*p, stderr);
+           putc(*p, ttyfp);
 }
 
 
@@ -107,17 +91,36 @@ static char *
 do_get( const char *prompt, int hidden )
 {
     char *buf;
+    byte cbuf[1];
     int c, n, i;
     FILE *fp;
     struct termios termsave;
 
+    if( !ttyfp )
+       init_ttyfp();
+
     last_prompt_len = 0;
     tty_printf( prompt );
     buf = m_alloc(n=50);
     i = 0;
-    fp = open_tty(hidden? &termsave: NULL);
-    while( (c=getc(fp)) != EOF && c != '\n' ) {
-       last_prompt_len++;
+
+    if( hidden ) {
+       struct termios term;
+
+       if( tcgetattr(fileno(ttyfp), &termsave) )
+           log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
+       term = termsave;
+       term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+       if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
+           log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
+    }
+
+    /* fixme: How can we avoid that the \n is echoed w/o disabling
+     * canonical mode - w/o this kill_prompt can't work */
+    while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
+       if( !hidden )
+           last_prompt_len++;
+       c = *cbuf;
        if( c == '\t' )
            c = ' ';
        else if( iscntrl(c) )
@@ -128,7 +131,11 @@ do_get( const char *prompt, int hidden )
        }
        buf[i++] = c;
     }
-    close_tty(fp, hidden? &termsave: NULL);
+
+    if( hidden ) {
+       if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
+           log_error("tcsetattr() failed: %s\n", strerror(errno) );
+    }
     buf[i] = 0;
     return buf;
 }
@@ -151,15 +158,16 @@ void
 tty_kill_prompt()
 {
     int i;
-#if 0
-    for(i=0; i < last_prompt_len; i ++ )
-       fputc('\b', stderr);
-    for(i=0; i < last_prompt_len; i ++ )
-       fputc(' ', stderr);
+
+    if( !ttyfp )
+       init_ttyfp();
+    if( !last_prompt_len )
+       return;
+    fputc('\r', ttyfp);
     for(i=0; i < last_prompt_len; i ++ )
-       fputc('\b', stderr);
-#endif
+       fputc(' ', ttyfp);
+    fputc('\r', ttyfp);
     last_prompt_len = 0;
-    fflush(stderr);
+    fflush(ttyfp);
 }