See ChangeLog: Mon Dec 14 21:18:49 CET 1998 Werner Koch

This commit is contained in:
Werner Koch 1998-12-14 20:22:42 +00:00
parent c6be02da77
commit 7a7a5630af
21 changed files with 642 additions and 524 deletions

View File

@ -2,6 +2,7 @@
* Check if an object (a message, detached sign, public key, or whatever)
is signed by definite user, i.e. define user
(userid, or any other unique identification) on command line.
--> NO: Use a script and --status-fd
* Change the internal represention of keyid into a struct which
can also hold the localid and extend the localid to hold information
@ -27,3 +28,9 @@
* Split key support (n-out-of-m)
* Check Berkeley BD - it is in glibc - any licensing problems?
* add an option to re-create a public key from a secret key; we
can do this in trustdb.c:verify_own_keys.
(special tool?)

7
THANKS
View File

@ -35,6 +35,7 @@ James Troup james@nocrew.org
Jean-loup Gailly gzip@prep.ai.mit.edu
Jens Bachem bachem@rrz.uni-koeln.de
John A. Martin jam@jamux.com
Johnny Teveßen j.tevessen@gmx.de
Jörg Schilling schilling@fokus.gmd.de
Jun Kuriyama kuriyama@sky.rim.or.jp
Karl Fogel kfogel@guanabana.onshore.com
@ -66,6 +67,7 @@ SL Baur steve@xemacs.org
Stefan Karrmann S.Karrmann@gmx.net
Steffen Ullrich ccrlphr@xensei.com
Steffen Zahn zahn@berlin.snafu.de
Susanne Schultz schultz@hsp.de
Thiago Jung Bauermann jungmann@usa.net
Thomas Roessler roessler@guug.de
Tom Spindler dogcow@home.merit.edu
@ -79,8 +81,9 @@ Werner Koch werner.koch@guug.de
Wim Vandeputte bunbun@reptile.rug.ac.be
nbecker@hns.com
Thanks to the German Unix User Group for providing FTP space and
Martin Hamilton for hosting the mailing list.
Thanks to the German Unix User Group for providing FTP space,
Martin Hamilton for hosting the mailing list and hsp for
hosting gnupg.org.
Many thanks to my wife Gerlinde for having so much patience with
me while hacking late in the evening.

13
TODO
View File

@ -6,8 +6,6 @@
* preferences of hash algorithms are not yet used.
* Check Berkeley BD - it is in glibc - any licensing problems?
* I noticed, that we sometimes have only 3 items in a trustrecord, but
a next pointer ro more records - check wehther the reuse code really
works. Maybe this is the reason for the "Hmmm public key lost"
@ -17,9 +15,6 @@
* should we flush the getkey.c caches while doing an import?
* The critical bit of signature subpackets is not yet supported; i.e.
it is ignored.
* We need a maintainence pass over the trustdb which flags
signatures as expired if the key used to make the signature has
expired. Maybe it is a good idea to store the exiration time
@ -44,13 +39,9 @@
* add checking of armor trailers
* remove all "Fixmes" ;-)
* add an option to re-create a public key from a secret key; we
can do this in trustdb.c:verify_own_keys.
(special tool?)
* change the fake_data stuff to mpi_set_opaque
* Use "user ID", "trustdb", "NOTE" and "WARNING".
* Replace Blowfish by Twofish
* Work on the library

View File

@ -1,3 +1,13 @@
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* random.c (read_random_source): Changed the interface to the
random gathering function.
(gather_faked): Use new interface.
* dynload.c (dynload_getfnc_fast_random_poll): Ditto.
(dynload_getfnc_gather_random): Ditto.
* rndlinux.c (gather_random): Ditto.
* rndunix.c (gather_random): Ditto.
Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* dynload.c (SYMBOL_VERSION): New to cope with system which needs

View File

@ -506,7 +506,8 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo,
int (*
dynload_getfnc_gather_random())(byte*, size_t*, int)
dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int,
size_t, int)
{
EXTLIST r;
void *sym;
@ -522,7 +523,8 @@ dynload_getfnc_gather_random())(byte*, size_t*, int)
while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) {
if( vers != 1 || class != 40 )
continue;
return (int (*)(byte*, size_t*, int))sym;
return (int (*)(void (*)(const void*, size_t, int), int,
size_t, int))sym;
}
}
return NULL;
@ -530,7 +532,7 @@ dynload_getfnc_gather_random())(byte*, size_t*, int)
void (*
dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int))
dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int)
{
EXTLIST r;
void *sym;
@ -546,7 +548,7 @@ dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int))
while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) {
if( vers != 1 || class != 41 )
continue;
return (void (*)( void (*)(const void*, size_t, int)))sym;
return (void (*)( void (*)(const void*, size_t, int), int))sym;
}
}
return NULL;

View File

@ -54,9 +54,10 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo,
unsigned (**get_nbits)( int algo, MPI *pkey ) );
int (*dynload_getfnc_gather_random(void))(byte*, size_t*, int);
int (*dynload_getfnc_gather_random(void))( void (*)(const void*, size_t, int),
int, size_t, int);
void (*dynload_getfnc_fast_random_poll(void)
)( void (*)(const void*, size_t, int));
)( void (*)(const void*, size_t, int), int );
#endif /*G10_CIPHER_DYNLOAD_H*/

View File

@ -94,8 +94,9 @@ static int faked_rng;
static void read_pool( byte *buffer, size_t length, int level );
static void add_randomness( const void *buffer, size_t length, int source );
static void random_poll(void);
static void read_random_source( byte *buffer, size_t length, int level );
static int gather_faked( byte *buffer, size_t *r_length, int level );
static void read_random_source( int requester, size_t length, int level);
static int gather_faked( void (*add)(const void*, size_t, int), int requester,
size_t length, int level );
static void
@ -137,7 +138,7 @@ quick_random_gen( int onoff )
{
int last;
read_random_source( NULL, 0, 0 ); /* load module */
read_random_source(0,0,0); /* init */
last = quick_test;
if( onoff != -1 )
quick_test = onoff;
@ -236,17 +237,13 @@ read_pool( byte *buffer, size_t length, int level )
/* for level 2 make sure that there is enough random in the pool */
if( level == 2 && pool_balance < length ) {
size_t needed;
byte *p;
if( pool_balance < 0 )
pool_balance = 0;
needed = length - pool_balance;
if( needed > POOLSIZE )
BUG();
p = secure_alloc ? m_alloc_secure( needed ) : m_alloc(needed);
read_random_source( p, needed, 2 ); /* read /dev/random */
add_randomness( p, needed, 3);
m_free(p);
read_random_source( 3, needed, 2 );
pool_balance += needed;
}
@ -321,17 +318,14 @@ add_randomness( const void *buffer, size_t length, int source )
static void
random_poll()
{
char buf[POOLSIZE/5];
read_random_source( buf, POOLSIZE/5, 1 );
add_randomness( buf, POOLSIZE/5, 2);
memset( buf, 0, POOLSIZE/5);
read_random_source( 2, POOLSIZE/5, 1 );
}
void
fast_random_poll()
{
static void (*fnc)( void (*)(const void*, size_t, int)) = NULL;
static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
static int initialized = 0;
if( !initialized ) {
@ -341,7 +335,7 @@ fast_random_poll()
fnc = dynload_getfnc_fast_random_poll();
}
if( fnc ) {
(*fnc)( add_randomness );
(*fnc)( add_randomness, 1 );
return;
}
@ -377,9 +371,10 @@ fast_random_poll()
static void
read_random_source( byte *buffer, size_t length, int level )
read_random_source( int requester, size_t length, int level )
{
static int (*fnc)(byte*, size_t*, int) = NULL;
static int (*fnc)(void (*)(const void*, size_t, int), int,
size_t, int) = NULL;
int nbytes;
int goodness;
@ -391,24 +386,21 @@ read_random_source( byte *buffer, size_t length, int level )
faked_rng = 1;
fnc = gather_faked;
}
if( !requester && !length && !level )
return; /* init only */
}
while( length ) {
nbytes = length;
goodness = (*fnc)( buffer, &nbytes, level );
if( goodness < 0 )
log_fatal("No way to gather entropy for the RNG\n");
buffer +=nbytes;
length -= nbytes;
/* FIXME: how can we handle the goodness */
}
if( (*fnc)( add_randomness, requester, length, level ) < 0 )
log_fatal("No way to gather entropy for the RNG\n");
}
static int
gather_faked( byte *buffer, size_t *r_length, int level )
gather_faked( void (*add)(const void*, size_t, int), int requester,
size_t length, int level )
{
static int initialized=0;
size_t length = *r_length;
size_t n;
char *buffer, *p;
if( !initialized ) {
log_info(_("WARNING: using insecure random number generator!!\n"));
@ -423,13 +415,17 @@ gather_faked( byte *buffer, size_t *r_length, int level )
#endif
}
p = buffer = m_alloc( length );
n = length;
#ifdef HAVE_RAND
while( length-- )
*buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
while( n-- )
*p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
#else
while( length-- )
*buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
while( n-- )
*p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
#endif
return 100; /* We really fake it ;-) */
add_randomness( buffer, length, requester );
m_free(buffer);
return 0; /* okay */
}

View File

@ -45,7 +45,8 @@
#endif
static int open_device( const char *name, int minor );
static int gather_random( byte *buffer, size_t *r_length, int level );
static int gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level );
#ifdef IS_MODULE
static void tty_printf(const char *fmt, ... )
@ -81,15 +82,15 @@ open_device( const char *name, int minor )
static int
gather_random( byte *buffer, size_t *r_length, int level )
gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level )
{
static int fd_urandom = -1;
static int fd_random = -1;
int fd;
int n;
int warn=0;
size_t length = *r_length;
/* note: we will always return the requested length */
byte buffer[768];
if( level >= 2 ) {
if( fd_random == -1 )
@ -101,7 +102,8 @@ gather_random( byte *buffer, size_t *r_length, int level )
fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
fd = fd_urandom;
}
do {
while( length ) {
fd_set rfds;
struct timeval tv;
int rc;
@ -125,20 +127,21 @@ gather_random( byte *buffer, size_t *r_length, int level )
}
do {
n = read(fd, buffer, length );
if( n >= 0 && n > length ) {
int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
n = read(fd, buffer, nbytes );
if( n >= 0 && n > nbytes ) {
g10_log_error("bogus read from random device (n=%d)\n", n );
n = length;
n = nbytes;
}
} while( n == -1 && errno == EINTR );
if( n == -1 )
g10_log_fatal("read error on random device: %s\n", strerror(errno));
assert( n <= length );
buffer += n;
(*add)( buffer, n, requester );
length -= n;
} while( length );
}
memset(buffer, 0, sizeof(buffer) );
return 100; /* always 100% useful at the requested level */
return 0; /* success */
}

View File

@ -669,13 +669,13 @@ read_a_msg( int fd, GATHER_MSG *msg )
static int
gather_random( char *buffer, size_t *r_length, int level )
gather_random( void (*add)(const void*, size_t, int), int requester,
size_t length, int level )
{
static pid_t gatherer_pid = 0;
static int pipedes[2];
GATHER_MSG msg;
size_t n;
size_t length = *r_length;
if( !gatherer_pid ) {
/* time to start the gatherer process */
@ -696,37 +696,45 @@ gather_random( char *buffer, size_t *r_length, int level )
}
/* now read from the gatherer */
if( read_a_msg( pipedes[0], &msg ) ) {
g10_log_error("reading from gatherer pipe failed: %s\n",
strerror(errno));
return -1;
}
while( length ) {
int goodness;
n = msg.ndata;
if( n > length )
n = length;
memcpy( buffer, msg.data, n );
if( read_a_msg( pipedes[0], &msg ) ) {
g10_log_error("reading from gatherer pipe failed: %s\n",
strerror(errno));
return -1;
}
*r_length = n;
if( level > 1 ) {
if( msg.usefulness > 30 )
return 100;
else if ( msg.usefulness )
return msg.usefulness * 100 / 30;
if( level > 1 ) {
if( msg.usefulness > 30 )
goodness = 100;
else if ( msg.usefulness )
goodness = msg.usefulness * 100 / 30;
else
goodness = 0;
}
else if( level ) {
if( msg.usefulness > 15 )
goodness = 100;
else if ( msg.usefulness )
goodness = msg.usefulness * 100 / 15;
else
goodness = 0;
}
else
return 0;
goodness = 100; /* goodness of level 0 is always 100 % */
n = msg.ndata;
if( n > length )
n = length;
(*add)( msg.data, n, requester );
/* this is the trick how e cope with the goodness */
length -= (ulong)n * goodness / 100;
}
else if( level ) {
if( msg.usefulness > 15 )
return 100;
else if ( msg.usefulness )
return msg.usefulness * 100 / 15;
else
return 0;
}
else
return 100; /* goodness of level 0 is always 100 % */
return 0;
}

View File

@ -8,14 +8,10 @@
Compatibility Notes
===================
GnuPG (>=0.4.1) is in compliance with RFC2440 despite these exeptions:
GnuPG (>0.4.5) is in compliance with RFC2440 despite these exceptions:
===> Please can someone check this <=========
* (5.1) The critical bit in signature subpackets is currently
ignored. This will be fixed soon.
* (5.2) GnuPG generates V4 signatures for all V4 keys. The option
--force-v3-sigs allows to override.
@ -23,13 +19,6 @@
Encrypted Session-Key Packets"; however a warning message is
issued if this option is active.
* (5.5.2) states that an implementaion MUST NOT create a v3 key
with an algorithm other than RSA. GnuPG has an option to
create an ElGamal key in a v3 packet; the properties of such
a key are as good as a v4 key. RFC1991 does not specifiy how
to create fingerprints for algorithms other than RSA and so it
is okay to choose a special format for ElGamal.
* (9.1) states that RSA SHOULD be implemented. This is not done
(except with an extension, usable outside the U.S.) due to
patent problems.

View File

@ -11,7 +11,7 @@ B<gpgm> [--homedir name] [--options file] [options] command [args]
=head1 DESCRIPTION
B<gpg> is the main program for the GnuPG system. B<gpgm> is a maintenance
tool which has some commands B<gpgm> does not have; it is there because
tool which has some commands B<gpg> does not have; it is there because
it does not handle sensitive data and therefore has no need to allocate
secure memory.
@ -92,7 +92,7 @@ B<--check-sigs> [I<names>]
B<--fingerprint> [I<names>]
List all keys with their fingerprints. This is the
same output as B<list-keys> but with the additonal output
same output as B<list-keys> but with the additional output
of a line with the fingerprint. May also be combined
with B<--list-sigs> or B<--check-sigs>.
@ -184,6 +184,9 @@ B<--export> [I<names>]
the file given with option "output". Use together
with B<-a> to mail those keys.
B<--export-all> [I<names>]
Same as B<--export> but does also export keys which
are not compatible to OpenPGP.
B<--export-secret-keys> [I<names>
Same as B<--export>, but does export the secret keys.
@ -452,7 +455,7 @@ B<--no-greeting>
enter batch mode.
B<--no-armor>
Assume the input data is not in ASCCI armored format.
Assume the input data is not in ASCII armored format.
B<--no-default-keyring>
Do not add the default keyrings to the list of

View File

@ -1,3 +1,10 @@
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* parse-packet.c (parse_signature): Now checks for critical bit
(parse_sig_subpkt): Splitted.
(parse_one_sig_subpkt): New.
* sig-check.c (do_check): handle critical bit.
Sun Dec 13 14:10:56 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* pcklist.c (select_algo_from_prefs): Preferences should

View File

@ -35,9 +35,12 @@
* as response to a prompt) we can use a simple search through the list.
* Translators should use the key as msgid, this is to keep the msgid short
* and to allow for easy changing of the helptexts.
*
* Mini gloassary:
*
* "user ID", "trustdb", "NOTE" and "WARNING".
*/
static struct helptexts { const char *key; const char *help; } helptexts[] = {
/* begin of list */

View File

@ -28,13 +28,6 @@ $Id$
force-v3-sigs
# Default is to use the newer compress algo 2, but PGP 5 does not
# like this, so we use the old one
# Hmm: Do we really need this ... preferences should decide which compress
# algo to use.
compress-algo 1
# If you do not use the Latin-1 (ISO-8859-1) charset, you should
# tell GnuPG which is the native character set. Please check
# the man page for supported character sets.
@ -45,10 +38,14 @@ compress-algo 1
# alias mynames -u 0x12345678 -u 0x456789ab -z 9
# everytime you use --mynames, it will be expanded to the options
# in the above defintion. The name of the alias may not be abbreviated.
# NOTE: This is not yet implemented
# lock tthe file only once for the lifetime of a process.
# lock the file only once for the lifetime of a process.
# if you do not define this, the lock will be obtained and released
# every time it is needed - normally this is not needed.
lock-once
# If you are not running one of the free operation systems
# you probably have to uncomment the next line:
#load-extension rndunix

View File

@ -200,6 +200,7 @@ struct packet_struct {
} while(0)
typedef enum {
SIGSUBPKT_TEST_CRITICAL=-3,
SIGSUBPKT_LIST_UNHASHED=-2,
SIGSUBPKT_LIST_HASHED =-1,
SIGSUBPKT_NONE = 0,

View File

@ -714,21 +714,60 @@ dump_sig_subpkt( int hashed, int type, int critical,
printf("%s)\n", p? p: "");
}
/****************
* Returns: >= 0 offset into buffer
* -1 unknown type
* -2 unsupported type
* -3 subpacket too short
*/
static int
parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
{
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_SIG_EXPIRE:
case SIGSUBPKT_KEY_EXPIRE:
if( n < 4 )
break;
return 0;
case SIGSUBPKT_EXPORTABLE:
if( !n )
break;
return 0;
case SIGSUBPKT_ISSUER:/* issuer key ID */
if( n < 8 )
break;
return 0;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
return 0;
case SIGSUBPKT_PRIV_ADD_SIG:
/* because we use private data, we check the GNUPG marker */
if( n < 24 )
break;
if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
return -2;
return 3;
default: return -1;
}
return -3;
}
const byte *
parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
{
int buflen;
int type;
int critical;
int offset;
size_t n;
if( !buffer )
return NULL;
buflen = (*buffer << 8) | buffer[1];
buffer += 2;
for(;;) {
if( !buflen )
return NULL; /* end of packets; not found */
while( buflen ) {
n = *buffer++; buflen--;
if( n == 255 ) {
if( buflen < 4 )
@ -754,49 +793,47 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
}
else
critical = 0;
if( reqtype < 0 ) /* list packets */
if( reqtype == SIGSUBPKT_TEST_CRITICAL ) {
if( critical ) {
if( n-1 > buflen+1 )
goto too_short;
if( parse_one_sig_subpkt(buffer+1, n-1, type ) < 0 ) {
log_info(_("subpacket of type %d has critical bit set\n"),
type);
return NULL; /* this is an error */
}
}
}
else if( reqtype < 0 ) /* list packets */
dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
type, critical, buffer, buflen, n );
else if( type == reqtype )
break; /* found */
else if( type == reqtype ) { /* found */
buffer++;
n--;
if( n > buflen )
goto too_short;
if( ret_n )
*ret_n = n;
offset = parse_one_sig_subpkt(buffer, n, type );
switch( offset ) {
case -3:
log_error("subpacket of type %d too short\n", type);
return NULL;
case -2:
return NULL;
case -1:
BUG(); /* not yet needed */
default:
break;
}
return buffer+offset;
}
buffer += n; buflen -=n;
}
buffer++;
n--;
if( n > buflen )
goto too_short;
if( ret_n )
*ret_n = n;
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_SIG_EXPIRE:
case SIGSUBPKT_KEY_EXPIRE:
if( n < 4 )
break;
return buffer;
case SIGSUBPKT_EXPORTABLE:
if( !n )
break;
return buffer;
case SIGSUBPKT_ISSUER:/* issuer key ID */
if( n < 8 )
break;
return buffer;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
return buffer;
case SIGSUBPKT_PRIV_ADD_SIG:
/* because we use private data, we check the GNUPG marker */
if( n < 24 )
break;
if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
return NULL;
return buffer+3;
default: BUG(); /* not yet needed */
}
log_error("subpacket of type %d too short\n", type);
return NULL;
if( reqtype == SIGSUBPKT_TEST_CRITICAL )
return buffer; /* as value true to indicate that there is no
/* critical bit we don't understand */
return NULL; /* end of packets; not found */
too_short:
log_error("buffer shorter than subpacket\n");
@ -899,10 +936,15 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
if( is_v4 ) { /*extract required information */
const byte *p;
/* FIXME: set sig->flags.unknown_critical is there is a
* critical bit set for packets which are not understood
* It does only make sense for hashed data.
*/
/* set sig->flags.unknown_critical if there is a
* critical bit set for packets which we do not understand */
if( !parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_TEST_CRITICAL, NULL)
|| !parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_TEST_CRITICAL,
NULL) )
{
sig->flags.unknown_critical = 1;
}
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
if( !p )
log_error("signature packet without timestamp\n");

View File

@ -222,6 +222,10 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest )
rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
cmp_help, &ctx );
mpi_free( result );
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad signature due to an unknown critical bit\n"));
rc = G10ERR_BAD_SIGN;
}
sig->flags.checked = 1;
sig->flags.valid = !rc;

View File

@ -1,3 +1,7 @@
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* types.h: fix for SUNPRO_C
Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* mpi.h (MPI): Changed the structure name to gcry_mpi and

View File

@ -91,7 +91,7 @@
#elif SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long u64;
#define HAVE_U64_TYPEDEF
#elif __GNUC__ >= 2
#elif __GNUC__ >= 2 || defined(__SUNPRO_C)
typedef unsigned long long u64;
#define HAVE_U64_TYPEDEF
#endif

View File

@ -1,3 +1,7 @@
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* de.po: Imported new version.
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* *.po: Changed some english strings.

767
po/de.po

File diff suppressed because it is too large Load Diff