update to popt 1.19

This commit is contained in:
Andrew Tridgell
2024-04-08 12:45:59 +10:00
parent 85c906f964
commit 4c8683c875
11 changed files with 3395 additions and 1422 deletions

View File

@@ -50,7 +50,7 @@ OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
OBJS3=progress.o pipe.o @MD5_ASM@ @ROLL_SIMD@ @ROLL_ASM@
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
popt/popthelp.o popt/poptparse.o popt/poptint.o
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@

View File

@@ -1084,6 +1084,8 @@ if test x"$with_included_popt" = x"yes"; then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="-I$srcdir/popt $CFLAGS"
AC_DEFINE(POPT_SYSCONFDIR, "/etc", [sysconfig dir for popt])
AC_DEFINE(PACKAGE, "rsync", [package name for rsync])
if test x"$ALLOCA" != x
then
# this can be removed when/if we add an included alloca.c;

959
popt/lookup3.c Normal file
View File

@@ -0,0 +1,959 @@
/* -------------------------------------------------------------------- */
/*
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
*
* These are functions for producing 32-bit hashes for hash table lookup.
* jlu32w(), jlu32l(), jlu32lpair(), jlu32b(), _JLU3_MIX(), and _JLU3_FINAL()
* are externally useful functions. Routines to test the hash are included
* if SELF_TEST is defined. You can use this free for any purpose. It's in
* the public domain. It has no warranty.
*
* You probably want to use jlu32l(). jlu32l() and jlu32b()
* hash byte arrays. jlu32l() is is faster than jlu32b() on
* little-endian machines. Intel and AMD are little-endian machines.
* On second thought, you probably want jlu32lpair(), which is identical to
* jlu32l() except it returns two 32-bit hashes for the price of one.
* You could implement jlu32bpair() if you wanted but I haven't bothered here.
*
* If you want to find a hash of, say, exactly 7 integers, do
* a = i1; b = i2; c = i3;
* _JLU3_MIX(a,b,c);
* a += i4; b += i5; c += i6;
* _JLU3_MIX(a,b,c);
* a += i7;
* _JLU3_FINAL(a,b,c);
* then use c as the hash value. If you have a variable size array of
* 4-byte integers to hash, use jlu32w(). If you have a byte array (like
* a character string), use jlu32l(). If you have several byte arrays, or
* a mix of things, see the comments above jlu32l().
*
* Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
* then mix those integers. This is fast (you can do a lot more thorough
* mixing with 12*3 instructions on 3 integers than you can with 3 instructions
* on 1 byte), but shoehorning those bytes into integers efficiently is messy.
*/
/* -------------------------------------------------------------------- */
#include <stdint.h>
#if defined(_JLU3_SELFTEST)
# define _JLU3_jlu32w 1
# define _JLU3_jlu32l 1
# define _JLU3_jlu32lpair 1
# define _JLU3_jlu32b 1
#endif
static const union _dbswap {
const uint32_t ui;
const unsigned char uc[4];
} endian = { .ui = 0x11223344 };
# define HASH_LITTLE_ENDIAN (endian.uc[0] == (unsigned char) 0x44)
# define HASH_BIG_ENDIAN (endian.uc[0] == (unsigned char) 0x11)
#ifndef ROTL32
# define ROTL32(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
#endif
/* NOTE: The _size parameter should be in bytes. */
#define _JLU3_INIT(_h, _size) (0xdeadbeef + ((uint32_t)(_size)) + (_h))
/* -------------------------------------------------------------------- */
/*
* _JLU3_MIX -- mix 3 32-bit values reversibly.
*
* This is reversible, so any information in (a,b,c) before _JLU3_MIX() is
* still in (a,b,c) after _JLU3_MIX().
*
* If four pairs of (a,b,c) inputs are run through _JLU3_MIX(), or through
* _JLU3_MIX() in reverse, there are at least 32 bits of the output that
* are sometimes the same for one pair and different for another pair.
* This was tested for:
* * pairs that differed by one bit, by two bits, in any combination
* of top bits of (a,b,c), or in any combination of bottom bits of
* (a,b,c).
* * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
* the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
* is commonly produced by subtraction) look like a single 1-bit
* difference.
* * the base values were pseudorandom, all zero but one bit set, or
* all zero plus a counter that starts at zero.
*
* Some k values for my "a-=c; a^=ROTL32(c,k); c+=b;" arrangement that
* satisfy this are
* 4 6 8 16 19 4
* 9 15 3 18 27 15
* 14 9 3 7 17 3
* Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
* for "differ" defined as + with a one-bit base and a two-bit delta. I
* used http://burtleburtle.net/bob/hash/avalanche.html to choose
* the operations, constants, and arrangements of the variables.
*
* This does not achieve avalanche. There are input bits of (a,b,c)
* that fail to affect some output bits of (a,b,c), especially of a. The
* most thoroughly mixed value is c, but it doesn't really even achieve
* avalanche in c.
*
* This allows some parallelism. Read-after-writes are good at doubling
* the number of bits affected, so the goal of mixing pulls in the opposite
* direction as the goal of parallelism. I did what I could. Rotates
* seem to cost as much as shifts on every machine I could lay my hands
* on, and rotates are much kinder to the top and bottom bits, so I used
* rotates.
*/
/* -------------------------------------------------------------------- */
#define _JLU3_MIX(a,b,c) \
{ \
a -= c; a ^= ROTL32(c, 4); c += b; \
b -= a; b ^= ROTL32(a, 6); a += c; \
c -= b; c ^= ROTL32(b, 8); b += a; \
a -= c; a ^= ROTL32(c,16); c += b; \
b -= a; b ^= ROTL32(a,19); a += c; \
c -= b; c ^= ROTL32(b, 4); b += a; \
}
/* -------------------------------------------------------------------- */
/**
* _JLU3_FINAL -- final mixing of 3 32-bit values (a,b,c) into c
*
* Pairs of (a,b,c) values differing in only a few bits will usually
* produce values of c that look totally different. This was tested for
* * pairs that differed by one bit, by two bits, in any combination
* of top bits of (a,b,c), or in any combination of bottom bits of
* (a,b,c).
* * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
* the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
* is commonly produced by subtraction) look like a single 1-bit
* difference.
* * the base values were pseudorandom, all zero but one bit set, or
* all zero plus a counter that starts at zero.
*
* These constants passed:
* 14 11 25 16 4 14 24
* 12 14 25 16 4 14 24
* and these came close:
* 4 8 15 26 3 22 24
* 10 8 15 26 3 22 24
* 11 8 15 26 3 22 24
*/
/* -------------------------------------------------------------------- */
#define _JLU3_FINAL(a,b,c) \
{ \
c ^= b; c -= ROTL32(b,14); \
a ^= c; a -= ROTL32(c,11); \
b ^= a; b -= ROTL32(a,25); \
c ^= b; c -= ROTL32(b,16); \
a ^= c; a -= ROTL32(c,4); \
b ^= a; b -= ROTL32(a,14); \
c ^= b; c -= ROTL32(b,24); \
}
#if defined(_JLU3_jlu32w)
uint32_t jlu32w(uint32_t h, const uint32_t *k, size_t size);
/* -------------------------------------------------------------------- */
/**
* This works on all machines. To be useful, it requires
* -- that the key be an array of uint32_t's, and
* -- that the size be the number of uint32_t's in the key
*
* The function jlu32w() is identical to jlu32l() on little-endian
* machines, and identical to jlu32b() on big-endian machines,
* except that the size has to be measured in uint32_ts rather than in
* bytes. jlu32l() is more complicated than jlu32w() only because
* jlu32l() has to dance around fitting the key bytes into registers.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint32_t values
* @param size the size of the key, in uint32_ts
* @return the lookup3 hash
*/
/* -------------------------------------------------------------------- */
uint32_t jlu32w(uint32_t h, const uint32_t *k, size_t size)
{
uint32_t a = _JLU3_INIT(h, (size * sizeof(*k)));
uint32_t b = a;
uint32_t c = a;
if (k == NULL)
goto exit;
/*----------------------------------------------- handle most of the key */
while (size > 3) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 3;
k += 3;
}
/*----------------------------------------- handle the last 3 uint32_t's */
switch (size) {
case 3 : c+=k[2];
case 2 : b+=k[1];
case 1 : a+=k[0];
_JLU3_FINAL(a,b,c);
/* fallthrough */
case 0:
break;
}
/*---------------------------------------------------- report the result */
exit:
return c;
}
#endif /* defined(_JLU3_jlu32w) */
#if defined(_JLU3_jlu32l)
uint32_t jlu32l(uint32_t h, const void *key, size_t size);
/* -------------------------------------------------------------------- */
/*
* jlu32l() -- hash a variable-length key into a 32-bit value
* h : can be any 4-byte value
* k : the key (the unaligned variable-length array of bytes)
* size : the size of the key, counting by bytes
* Returns a 32-bit value. Every bit of the key affects every bit of
* the return value. Two keys differing by one or two bits will have
* totally different hash values.
*
* The best hash table sizes are powers of 2. There is no need to do
* mod a prime (mod is sooo slow!). If you need less than 32 bits,
* use a bitmask. For example, if you need only 10 bits, do
* h = (h & hashmask(10));
* In which case, the hash table should have hashsize(10) elements.
*
* If you are hashing n strings (uint8_t **)k, do it like this:
* for (i=0, h=0; i<n; ++i) h = jlu32l(h, k[i], len[i]);
*
* By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
* code any way you wish, private, educational, or commercial. It's free.
*
* Use for hash table lookup, or anything where one collision in 2^^32 is
* acceptable. Do NOT use for cryptographic purposes.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint8_t values
* @param size the size of the key
* @return the lookup3 hash
*/
/* -------------------------------------------------------------------- */
uint32_t jlu32l(uint32_t h, const void *key, size_t size)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(h, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
goto exit;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > 12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff; a+=k[0]; break;
case 6: b += k[1]&0xffff; a+=k[0]; break;
case 5: b += k[1]&0xff; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff; break;
case 2: a += k[0]&0xffff; break;
case 1: a += k[0]&0xff; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0] break;
case 11: c += ((uint32_t)k8[10])<<16; /* fallthrough */
case 10: c += ((uint32_t)k8[9])<<8; /* fallthrough */
case 9: c += k8[8]; /* fallthrough */
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<16; /* fallthrough */
case 6: b += ((uint32_t)k8[5])<<8; /* fallthrough */
case 5: b += k8[4]; /* fallthrough */
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<16; /* fallthrough */
case 2: a += ((uint32_t)k8[1])<<8; /* fallthrough */
case 1: a += k8[0]; break;
case 0: goto exit;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*----------- all but last block: aligned reads and different mixing */
while (size > 12) {
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
_JLU3_MIX(a,b,c);
size -= 12;
k += 6;
}
/*------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch (size) {
case 12:
c += k[4]+(((uint32_t)k[5])<<16);
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 11:
c += ((uint32_t)k8[10])<<16;
/* fallthrough */
case 10:
c += (uint32_t)k[4];
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 9:
c += (uint32_t)k8[8];
/* fallthrough */
case 8:
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 7:
b += ((uint32_t)k8[6])<<16;
/* fallthrough */
case 6:
b += (uint32_t)k[2];
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 5:
b += (uint32_t)k8[4];
/* fallthrough */
case 4:
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 3:
a += ((uint32_t)k8[2])<<16;
/* fallthrough */
case 2:
a += (uint32_t)k[0];
break;
case 1:
a += (uint32_t)k8[0];
break;
case 0:
goto exit;
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > 12) {
a += (uint32_t)k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += (uint32_t)k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += (uint32_t)k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) {
case 12: c += ((uint32_t)k[11])<<24; /* fallthrough */
case 11: c += ((uint32_t)k[10])<<16; /* fallthrough */
case 10: c += ((uint32_t)k[9])<<8; /* fallthrough */
case 9: c += (uint32_t)k[8]; /* fallthrough */
case 8: b += ((uint32_t)k[7])<<24; /* fallthrough */
case 7: b += ((uint32_t)k[6])<<16; /* fallthrough */
case 6: b += ((uint32_t)k[5])<<8; /* fallthrough */
case 5: b += (uint32_t)k[4]; /* fallthrough */
case 4: a += ((uint32_t)k[3])<<24; /* fallthrough */
case 3: a += ((uint32_t)k[2])<<16; /* fallthrough */
case 2: a += ((uint32_t)k[1])<<8; /* fallthrough */
case 1: a += (uint32_t)k[0];
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
return c;
}
#endif /* defined(_JLU3_jlu32l) */
#if defined(_JLU3_jlu32lpair)
/**
* jlu32lpair: return 2 32-bit hash values.
*
* This is identical to jlu32l(), except it returns two 32-bit hash
* values instead of just one. This is good enough for hash table
* lookup with 2^^64 buckets, or if you want a second hash if you're not
* happy with the first, or if you want a probably-unique 64-bit ID for
* the key. *pc is better mixed than *pb, so use *pc first. If you want
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
*
* @param h the previous hash, or an arbitrary value
* @param *key the key, an array of uint8_t values
* @param size the size of the key in bytes
* @retval *pc, IN: primary initval, OUT: primary hash
* *retval *pb IN: secondary initval, OUT: secondary hash
*/
void jlu32lpair(const void *key, size_t size, uint32_t *pc, uint32_t *pb)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(*pc, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
goto exit;
c += *pb; /* Add the secondary hash. */
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > (size_t)12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff; a+=k[0]; break;
case 6: b += k[1]&0xffff; a+=k[0]; break;
case 5: b += k[1]&0xff; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff; break;
case 2: a += k[0]&0xffff; break;
case 1: a += k[0]&0xff; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += ((uint32_t)k8[10])<<16; /* fallthrough */
case 10: c += ((uint32_t)k8[9])<<8; /* fallthrough */
case 9: c += k8[8]; /* fallthrough */
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<16; /* fallthrough */
case 6: b += ((uint32_t)k8[5])<<8; /* fallthrough */
case 5: b += k8[4]; /* fallthrough */
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<16; /* fallthrough */
case 2: a += ((uint32_t)k8[1])<<8; /* fallthrough */
case 1: a += k8[0]; break;
case 0: goto exit;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*----------- all but last block: aligned reads and different mixing */
while (size > (size_t)12) {
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
_JLU3_MIX(a,b,c);
size -= 12;
k += 6;
}
/*------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch (size) {
case 12:
c += k[4]+(((uint32_t)k[5])<<16);
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 11:
c += ((uint32_t)k8[10])<<16;
/* fallthrough */
case 10:
c += k[4];
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 9:
c += k8[8];
/* fallthrough */
case 8:
b += k[2]+(((uint32_t)k[3])<<16);
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 7:
b += ((uint32_t)k8[6])<<16;
/* fallthrough */
case 6:
b += k[2];
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 5:
b += k8[4];
/* fallthrough */
case 4:
a += k[0]+(((uint32_t)k[1])<<16);
break;
case 3:
a += ((uint32_t)k8[2])<<16;
/* fallthrough */
case 2:
a += k[0];
break;
case 1:
a += k8[0];
break;
case 0:
goto exit;
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > (size_t)12) {
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) {
case 12: c += ((uint32_t)k[11])<<24; /* fallthrough */
case 11: c += ((uint32_t)k[10])<<16; /* fallthrough */
case 10: c += ((uint32_t)k[9])<<8; /* fallthrough */
case 9: c += k[8]; /* fallthrough */
case 8: b += ((uint32_t)k[7])<<24; /* fallthrough */
case 7: b += ((uint32_t)k[6])<<16; /* fallthrough */
case 6: b += ((uint32_t)k[5])<<8; /* fallthrough */
case 5: b += k[4]; /* fallthrough */
case 4: a += ((uint32_t)k[3])<<24; /* fallthrough */
case 3: a += ((uint32_t)k[2])<<16; /* fallthrough */
case 2: a += ((uint32_t)k[1])<<8; /* fallthrough */
case 1: a += k[0];
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
*pc = c;
*pb = b;
return;
}
#endif /* defined(_JLU3_jlu32lpair) */
#if defined(_JLU3_jlu32b)
uint32_t jlu32b(uint32_t h, const void *key, size_t size);
/*
* jlu32b():
* This is the same as jlu32w() on big-endian machines. It is different
* from jlu32l() on all machines. jlu32b() takes advantage of
* big-endian byte ordering.
*
* @param h the previous hash, or an arbitrary value
* @param *k the key, an array of uint8_t values
* @param size the size of the key
* @return the lookup3 hash
*/
uint32_t jlu32b(uint32_t h, const void *key, size_t size)
{
union { const void *ptr; size_t i; } u;
uint32_t a = _JLU3_INIT(h, size);
uint32_t b = a;
uint32_t c = a;
if (key == NULL)
return h;
u.ptr = key;
if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
#ifdef VALGRIND
const uint8_t *k8;
#endif
/*-- all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (size > 12) {
a += k[0];
b += k[1];
c += k[2];
_JLU3_MIX(a,b,c);
size -= 12;
k += 3;
}
/*------------------------- handle the last (probably partial) block */
/*
* "k[2]<<8" actually reads beyond the end of the string, but
* then shifts out the part it's not allowed to read. Because the
* string is aligned, the illegal read is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch (size) {
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
case 10: c += k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
case 9: c += k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
case 8: b += k[1]; a+=k[0]; break;
case 7: b += k[1]&0xffffff00; a+=k[0]; break;
case 6: b += k[1]&0xffff0000; a+=k[0]; break;
case 5: b += k[1]&0xff000000; a+=k[0]; break;
case 4: a += k[0]; break;
case 3: a += k[0]&0xffffff00; break;
case 2: a += k[0]&0xffff0000; break;
case 1: a += k[0]&0xff000000; break;
case 0: goto exit;
}
#else /* make valgrind happy */
k8 = (const uint8_t *)k;
switch (size) { /* all the case statements fall through */
case 12: c += k[2]; b+=k[1]; a+=k[0]; break;
case 11: c += ((uint32_t)k8[10])<<8; /* fallthrough */
case 10: c += ((uint32_t)k8[9])<<16; /* fallthrough */
case 9: c += ((uint32_t)k8[8])<<24; /* fallthrough */
case 8: b += k[1]; a+=k[0]; break;
case 7: b += ((uint32_t)k8[6])<<8; /* fallthrough */
case 6: b += ((uint32_t)k8[5])<<16; /* fallthrough */
case 5: b += ((uint32_t)k8[4])<<24; /* fallthrough */
case 4: a += k[0]; break;
case 3: a += ((uint32_t)k8[2])<<8; /* fallthrough */
case 2: a += ((uint32_t)k8[1])<<16; /* fallthrough */
case 1: a += ((uint32_t)k8[0])<<24; break;
case 0: goto exit;
}
#endif /* !VALGRIND */
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*----------- all but the last block: affect some 32 bits of (a,b,c) */
while (size > 12) {
a += ((uint32_t)k[0])<<24;
a += ((uint32_t)k[1])<<16;
a += ((uint32_t)k[2])<<8;
a += ((uint32_t)k[3]);
b += ((uint32_t)k[4])<<24;
b += ((uint32_t)k[5])<<16;
b += ((uint32_t)k[6])<<8;
b += ((uint32_t)k[7]);
c += ((uint32_t)k[8])<<24;
c += ((uint32_t)k[9])<<16;
c += ((uint32_t)k[10])<<8;
c += ((uint32_t)k[11]);
_JLU3_MIX(a,b,c);
size -= 12;
k += 12;
}
/*---------------------------- last block: affect all 32 bits of (c) */
switch (size) { /* all the case statements fall through */
case 12: c += k[11]; /* fallthrough */
case 11: c += ((uint32_t)k[10])<<8; /* fallthrough */
case 10: c += ((uint32_t)k[9])<<16; /* fallthrough */
case 9: c += ((uint32_t)k[8])<<24; /* fallthrough */
case 8: b += k[7]; /* fallthrough */
case 7: b += ((uint32_t)k[6])<<8; /* fallthrough */
case 6: b += ((uint32_t)k[5])<<16; /* fallthrough */
case 5: b += ((uint32_t)k[4])<<24; /* fallthrough */
case 4: a += k[3]; /* fallthrough */
case 3: a += ((uint32_t)k[2])<<8; /* fallthrough */
case 2: a += ((uint32_t)k[1])<<16; /* fallthrough */
case 1: a += ((uint32_t)k[0])<<24; /* fallthrough */
break;
case 0:
goto exit;
}
}
_JLU3_FINAL(a,b,c);
exit:
return c;
}
#endif /* defined(_JLU3_jlu32b) */
#if defined(_JLU3_SELFTEST)
/* used for timings */
static void driver1(void)
{
uint8_t buf[256];
uint32_t i;
uint32_t h=0;
time_t a,z;
time(&a);
for (i=0; i<256; ++i) buf[i] = 'x';
for (i=0; i<1; ++i) {
h = jlu32l(h, &buf[0], sizeof(buf[0]));
}
time(&z);
if (z-a > 0) printf("time %d %.8x\n", (int)(z-a), h);
}
/* check that every input bit changes every output bit half the time */
#define HASHSTATE 1
#define HASHLEN 1
#define MAXPAIR 60
#define MAXLEN 70
static void driver2(void)
{
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
uint32_t x[HASHSTATE],y[HASHSTATE];
uint32_t hlen;
printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
for (hlen=0; hlen < MAXLEN; ++hlen) {
z=0;
for (i=0; i<hlen; ++i) { /*-------------- for each input byte, */
for (j=0; j<8; ++j) { /*--------------- for each input bit, */
for (m=1; m<8; ++m) { /*---- for several possible initvals, */
for (l=0; l<HASHSTATE; ++l)
e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0);
/* check that every output bit is affected by that input bit */
for (k=0; k<MAXPAIR; k+=2) {
uint32_t finished=1;
/* keys have one bit different */
for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
/* have a and b be two keys differing in only one bit */
a[i] ^= (k<<j);
a[i] ^= (k>>(8-j));
c[0] = jlu32l(m, a, hlen);
b[i] ^= ((k+1)<<j);
b[i] ^= ((k+1)>>(8-j));
d[0] = jlu32l(m, b, hlen);
/* check every bit is 1, 0, set, and not set at least once */
for (l=0; l<HASHSTATE; ++l) {
e[l] &= (c[l]^d[l]);
f[l] &= ~(c[l]^d[l]);
g[l] &= c[l];
h[l] &= ~c[l];
x[l] &= d[l];
y[l] &= ~d[l];
if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
}
if (finished) break;
}
if (k>z) z=k;
if (k == MAXPAIR) {
printf("Some bit didn't change: ");
printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
e[0],f[0],g[0],h[0],x[0],y[0]);
printf("i %u j %u m %u len %u\n", i, j, m, hlen);
}
if (z == MAXPAIR) goto done;
}
}
}
done:
if (z < MAXPAIR) {
printf("Mix success %2u bytes %2u initvals ",i,m);
printf("required %u trials\n", z/2);
}
}
printf("\n");
}
/* Check for reading beyond the end of the buffer and alignment problems */
static void driver3(void)
{
uint8_t buf[MAXLEN+20], *b;
uint32_t len;
uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
uint32_t h;
uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
uint32_t i;
uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
uint32_t j;
uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
uint32_t ref,x,y;
uint8_t *p;
uint32_t m = 13;
printf("Endianness. These lines should all be the same (for values filled in):\n");
printf("%.8x %.8x %.8x\n",
jlu32w(m, (const uint32_t *)q, (sizeof(q)-1)/4),
jlu32w(m, (const uint32_t *)q, (sizeof(q)-5)/4),
jlu32w(m, (const uint32_t *)q, (sizeof(q)-9)/4));
p = q;
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qq[1];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qqq[2];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
p = &qqqq[3];
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
jlu32l(m, p, sizeof(q)-1), jlu32l(m, p, sizeof(q)-2),
jlu32l(m, p, sizeof(q)-3), jlu32l(m, p, sizeof(q)-4),
jlu32l(m, p, sizeof(q)-5), jlu32l(m, p, sizeof(q)-6),
jlu32l(m, p, sizeof(q)-7), jlu32l(m, p, sizeof(q)-8),
jlu32l(m, p, sizeof(q)-9), jlu32l(m, p, sizeof(q)-10),
jlu32l(m, p, sizeof(q)-11), jlu32l(m, p, sizeof(q)-12));
printf("\n");
for (h=0, b=buf+1; h<8; ++h, ++b) {
for (i=0; i<MAXLEN; ++i) {
len = i;
for (j=0; j<i; ++j)
*(b+j)=0;
/* these should all be equal */
m = 1;
ref = jlu32l(m, b, len);
*(b+i)=(uint8_t)~0;
*(b-1)=(uint8_t)~0;
x = jlu32l(m, b, len);
y = jlu32l(m, b, len);
if ((ref != x) || (ref != y))
printf("alignment error: %.8x %.8x %.8x %u %u\n",ref,x,y, h, i);
}
}
}
/* check for problems with nulls */
static void driver4(void)
{
uint8_t buf[1];
uint32_t h;
uint32_t i;
uint32_t state[HASHSTATE];
buf[0] = ~0;
for (i=0; i<HASHSTATE; ++i)
state[i] = 1;
printf("These should all be different\n");
h = 0;
for (i=0; i<8; ++i) {
h = jlu32l(h, buf, 0);
printf("%2ld 0-byte strings, hash is %.8x\n", (long)i, h);
}
}
int main(int argc, char ** argv)
{
driver1(); /* test that the key is hashed: used for timings */
driver2(); /* test that whole key is hashed thoroughly */
driver3(); /* test that nothing but the key is hashed */
driver4(); /* test hashing multiple buffers (all buffers are null) */
return 1;
}
#endif /* _JLU3_SELFTEST */

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
/** \file popt/popt.h
* \ingroup popt
/** @file
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
@@ -13,45 +12,49 @@
#define POPT_OPTION_DEPTH 10
/** \ingroup popt
/**
* \name Arg type identifiers
*/
/*@{*/
#define POPT_ARG_NONE 0 /*!< no arg */
#define POPT_ARG_STRING 1 /*!< arg will be saved as string */
#define POPT_ARG_INT 2 /*!< arg will be converted to int */
#define POPT_ARG_LONG 3 /*!< arg will be converted to long */
#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */
#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be
#define POPT_ARG_NONE 0U /*!< no arg */
#define POPT_ARG_STRING 1U /*!< arg will be saved as string */
#define POPT_ARG_INT 2U /*!< arg ==> int */
#define POPT_ARG_LONG 3U /*!< arg ==> long */
#define POPT_ARG_INCLUDE_TABLE 4U /*!< arg points to table */
#define POPT_ARG_CALLBACK 5U /*!< table-wide callback... must be
set first in table; arg points
to callback, descrip points to
callback data to pass */
#define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain
#define POPT_ARG_INTL_DOMAIN 6U /*!< set the translation domain
for this table and any
included tables; arg points
to the domain string */
#define POPT_ARG_VAL 7 /*!< arg should take value val */
#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */
#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */
#define POPT_ARG_VAL 7U /*!< arg should take value val */
#define POPT_ARG_FLOAT 8U /*!< arg ==> float */
#define POPT_ARG_DOUBLE 9U /*!< arg ==> double */
#define POPT_ARG_LONGLONG 10U /*!< arg ==> long long */
#define POPT_ARG_MASK 0x0000FFFF
/*@}*/
#define POPT_ARG_MAINCALL (16U+11U) /*!< EXPERIMENTAL: return (*arg) (argc, argv) */
#define POPT_ARG_ARGV 12U /*!< dupe'd arg appended to realloc'd argv array. */
#define POPT_ARG_SHORT 13U /*!< arg ==> short */
#define POPT_ARG_BITSET (16U+14U) /*!< arg ==> bit set */
/** \ingroup popt
#define POPT_ARG_MASK 0x000000FFU
#define POPT_GROUP_MASK 0x0000FF00U
/**
* \name Arg modifiers
*/
/*@{*/
#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */
#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */
#define POPT_ARGFLAG_ONEDASH 0x80000000U /*!< allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000U /*!< don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000U /*!< strip this arg from argv(only applies to long args) */
#define POPT_ARGFLAG_OPTIONAL 0x10000000U /*!< arg may be missing */
#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */
#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */
#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */
#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */
#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */
#define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */
#define POPT_ARGFLAG_OR 0x08000000U /*!< arg will be or'ed */
#define POPT_ARGFLAG_NOR 0x09000000U /*!< arg will be nor'ed */
#define POPT_ARGFLAG_AND 0x04000000U /*!< arg will be and'ed */
#define POPT_ARGFLAG_NAND 0x05000000U /*!< arg will be nand'ed */
#define POPT_ARGFLAG_XOR 0x02000000U /*!< arg will be xor'ed */
#define POPT_ARGFLAG_NOT 0x01000000U /*!< arg will be negated */
#define POPT_ARGFLAG_LOGICALOPS \
(POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR)
@@ -60,158 +63,126 @@
#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND)
/*!< clear arg bit(s) */
#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */
#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000U /*!< show default value in --help */
#define POPT_ARGFLAG_RANDOM 0x00400000U /*!< random value in [1,arg] */
#define POPT_ARGFLAG_TOGGLE 0x00200000U /*!< permit --[no]opt prefix toggle */
/*@}*/
/** \ingroup popt
/**
* \name Callback modifiers
*/
/*@{*/
#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line,
#define POPT_CBFLAG_PRE 0x80000000U /*!< call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000U /*!< call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000U /*!< use data from the include line,
not the subtable */
#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */
#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */
/*@}*/
#define POPT_CBFLAG_SKIPOPTION 0x10000000U /*!< don't callback with option */
#define POPT_CBFLAG_CONTINUE 0x08000000U /*!< continue callbacks with option */
/** \ingroup popt
/**
* \name Error return values
*/
/*@{*/
#define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
#define POPT_ERROR_UNWANTEDARG -12 /*!< option does not take an argument */
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
#define POPT_ERROR_BADQUOTE -15 /*!< error in parameter quoting */
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */
#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */
#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */
#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */
#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */
/*@}*/
#define POPT_ERROR_BADCONFIG -22 /*!< config file failed sanity test */
/** \ingroup popt
/**
* \name poptBadOption() flags
*/
/*@{*/
#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */
/*@}*/
#define POPT_BADOPTION_NOALIAS (1U << 0) /*!< don't go into an alias */
/** \ingroup popt
/**
* \name poptGetContext() flags
*/
/*@{*/
#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */
#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */
/*@}*/
#define POPT_CONTEXT_NO_EXEC (1U << 0) /*!< ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1U << 1) /*!< pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1U << 2) /*!< options can't follow args */
#define POPT_CONTEXT_ARG_OPTS (1U << 4) /*!< return args as options with value 0 */
/** \ingroup popt
/**
*/
struct poptOption {
/*@observer@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argInfo;
/*@shared@*/ /*@null@*/
char shortName; /*!< may be '\0' */
unsigned int argInfo; /*!< type of argument expected after the option */
void * arg; /*!< depends on argInfo */
int val; /*!< 0 means don't return, just update flag */
/*@observer@*/ /*@null@*/
int val; /*!< 0 means don't return, just update arg */
const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/
const char * argDescrip; /*!< argument description for autohelp */
const char * argDescrip; /*!< argument description for autohelp -- may be NULL */
};
/** \ingroup popt
/**
* A popt alias argument for poptAddAlias().
*/
struct poptAlias {
/*@owned@*/ /*@null@*/
const char * longName; /*!< may be NULL */
char shortName; /*!< may be NUL */
int argc;
/*@owned@*/
const char ** argv; /*!< must be free()able */
};
/** \ingroup popt
/**
* A popt alias or exec argument for poptAddItem().
*/
/*@-exporttype@*/
typedef struct poptItem_s {
struct poptOption option; /*!< alias/exec name(s) and description. */
int argc; /*!< (alias) no. of args. */
/*@owned@*/
const char ** argv; /*!< (alias) args, must be free()able. */
} * poptItem;
/*@=exporttype@*/
/** \ingroup popt
/**
* \name Auto-generated help/usage
*/
/*@{*/
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptAliasOptions[];
/*@=exportvar@*/
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
0, "Options implemented via popt alias/exec:", NULL },
/**
* Auto help table options.
*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptHelpOptions[];
/*@=exportvar@*/
/*@-exportvar@*/
/*@unchecked@*/ /*@observer@*/
extern struct poptOption * poptHelpOptionsI18N;
/*@=exportvar@*/
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options:", NULL },
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
/*@}*/
#define POPT_TABLEEND { NULL, '\0', 0, NULL, 0, NULL, NULL }
/** \ingroup popt
/**
*/
/*@-exporttype@*/
typedef /*@abstract@*/ struct poptContext_s * poptContext;
/*@=exporttype@*/
typedef struct poptContext_s * poptContext;
/** \ingroup popt
/**
*/
#ifndef __cplusplus
/*@-exporttype -typeuse@*/
typedef struct poptOption * poptOption;
/*@=exporttype =typeuse@*/
#endif
/*@-exportconst@*/
/**
*/
enum poptCallbackReason {
POPT_CALLBACK_REASON_PRE = 0,
POPT_CALLBACK_REASON_POST = 1,
POPT_CALLBACK_REASON_OPTION = 2
};
/*@=exportconst@*/
#ifdef __cplusplus
extern "C" {
#endif
/*@-type@*/
/** \ingroup popt
/**
* Table callback prototype.
* @param con context
* @param reason reason for callback
@@ -221,13 +192,18 @@ extern "C" {
*/
typedef void (*poptCallbackType) (poptContext con,
enum poptCallbackReason reason,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * arg,
/*@null@*/ const void * data)
/*@globals internalState @*/
/*@modifies internalState @*/;
const struct poptOption * opt,
const char * arg,
const void * data);
/** \ingroup popt
/**
* Destroy context.
* @param con context
* @return NULL always
*/
poptContext poptFreeContext( poptContext con);
/**
* Initialize popt context.
* @param name context name (usually argv[0] program name)
* @param argc no. of arguments
@@ -236,97 +212,90 @@ typedef void (*poptCallbackType) (poptContext con,
* @param flags or'd POPT_CONTEXT_* bits
* @return initialized popt context
*/
/*@only@*/ /*@null@*/
poptContext poptGetContext(
/*@dependent@*/ /*@keep@*/ const char * name,
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
int flags)
/*@*/;
const char * name,
int argc, const char ** argv,
const struct poptOption * options,
unsigned int flags);
/** \ingroup popt
/**
* Destroy context (alternative implementation).
* @param con context
* @return NULL always
*/
poptContext poptFini( poptContext con);
/**
* Initialize popt context (alternative implementation).
* This routine does poptGetContext() and then poptReadConfigFiles().
* @param argc no. of arguments
* @param argv argument array
* @param options address of popt option table
* @param configPaths colon separated file path(s) to read.
* @return initialized popt context (NULL on error).
*/
poptContext poptInit(int argc, const char ** argv,
const struct poptOption * options,
const char * configPaths);
/**
* Reinitialize popt context.
* @param con context
*/
/*@unused@*/
void poptResetContext(/*@null@*/poptContext con)
/*@modifies con @*/;
void poptResetContext(poptContext con);
/** \ingroup popt
/**
* Return value of next option found.
* @param con context
* @return next option val, -1 on last item, POPT_ERROR_* on error
*/
int poptGetNextOpt(/*@null@*/poptContext con)
/*@globals fileSystem, internalState @*/
/*@modifies con, fileSystem, internalState @*/;
int poptGetNextOpt(poptContext con);
/** \ingroup popt
/**
* Return next option argument (if any).
* @param con context
* @return option argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptGetOptArg(/*@null@*/poptContext con)
/*@modifies con @*/;
char * poptGetOptArg(poptContext con);
/** \ingroup popt
/**
* Return next argument.
* @param con context
* @return next argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptGetArg(/*@null@*/poptContext con)
/*@modifies con @*/;
const char * poptGetArg(poptContext con);
/** \ingroup popt
/**
* Peek at current argument.
* @param con context
* @return current argument, NULL if no argument is available
*/
/*@observer@*/ /*@null@*/ /*@unused@*/
const char * poptPeekArg(/*@null@*/poptContext con)
/*@*/;
const char * poptPeekArg(poptContext con);
/** \ingroup popt
/**
* Return remaining arguments.
* @param con context
* @return argument array, NULL terminated
*/
/*@observer@*/ /*@null@*/
const char ** poptGetArgs(/*@null@*/poptContext con)
/*@modifies con @*/;
const char ** poptGetArgs(poptContext con);
/** \ingroup popt
/**
* Return the option which caused the most recent error.
* @param con context
* @param flags
* @return offending option
*/
/*@observer@*/
const char * poptBadOption(/*@null@*/poptContext con, int flags)
/*@*/;
const char * poptBadOption(poptContext con, unsigned int flags);
/** \ingroup popt
* Destroy context.
* @param con context
* @return NULL always
*/
/*@null@*/
poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
/**
* Add arguments to context.
* @param con context
* @param argv argument array, NULL terminated
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
*/
/*@unused@*/
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
/*@modifies con @*/;
int poptStuffArgs(poptContext con, const char ** argv);
/** \ingroup popt
/**
* Add alias to context.
* @todo Pass alias by reference, not value.
* @deprecated Use poptAddItem instead.
@@ -335,44 +304,64 @@ int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
* @param flags (unused)
* @return 0 on success
*/
/*@unused@*/
int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
/*@modifies con @*/;
int poptAddAlias(poptContext con, struct poptAlias alias, int flags);
/** \ingroup popt
/**
* Add alias/exec item to context.
* @param con context
* @param newItem alias/exec item to add
* @param flags 0 for alias, 1 for exec
* @return 0 on success
*/
int poptAddItem(poptContext con, poptItem newItem, int flags)
/*@modifies con @*/;
int poptAddItem(poptContext con, poptItem newItem, int flags);
/** \ingroup popt
/**
* Test path/file for config file sanity (regular file, permissions etc)
* @param fn file name
* @return 1 on OK, 0 on NOTOK.
*/
int poptSaneFile(const char * fn);
/**
* Read a file into a buffer.
* @param fn file name
* @retval *bp buffer (malloc'd) (or NULL)
* @retval *nbp no. of bytes in buffer (including final NUL) (or NULL)
* @param flags 1 to trim escaped newlines
* return 0 on success
*/
int poptReadFile(const char * fn, char ** bp,
size_t * nbp, int flags);
#define POPT_READFILE_TRIMNEWLINES 1
/**
* Read configuration file.
* @param con context
* @param fn file name to read
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
int poptReadConfigFile(poptContext con, const char * fn)
/*@globals errno, fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
errno, fileSystem, internalState @*/;
int poptReadConfigFile(poptContext con, const char * fn);
/** \ingroup popt
/**
* Read configuration file(s).
* Colon separated files to read, looping over poptReadConfigFile().
* Note that an '@' character preceding a path in the list will
* also perform additional sanity checks on the file before reading.
* @param con context
* @param paths colon separated file name(s) to read
* @return 0 on success, POPT_ERROR_BADCONFIG on failure
*/
int poptReadConfigFiles(poptContext con, const char * paths);
/**
* Read default configuration from /etc/popt and $HOME/.popt.
* @param con context
* @param useEnv (unused)
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
/*@unused@*/
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
/*@globals fileSystem, internalState @*/
/*@modifies con->execs, con->numExecs,
fileSystem, internalState @*/;
int poptReadDefaultConfig(poptContext con, int useEnv);
/** \ingroup popt
/**
* Duplicate an argument array.
* @note: The argument array is malloc'd as a single area, so only argv must
* be free'd.
@@ -383,12 +372,11 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
* @retval argvPtr address of returned argument array
* @return 0 on success, POPT_ERROR_NOARG on failure
*/
int poptDupArgv(int argc, /*@null@*/ const char **argv,
/*@null@*/ /*@out@*/ int * argcPtr,
/*@null@*/ /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
int poptDupArgv(int argc, const char **argv,
int * argcPtr,
const char *** argvPtr);
/** \ingroup popt
/**
* Parse a string into an argument array.
* The parse allows ', ", and \ quoting, but ' is treated the same as " and
* both may include \ quotes.
@@ -400,10 +388,9 @@ int poptDupArgv(int argc, /*@null@*/ const char **argv,
* @retval argvPtr address of returned argument array
*/
int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
int * argcPtr, const char *** argvPtr);
/** \ingroup popt
/**
* Parses an input configuration file and returns an string that is a
* command line. For use with popt. You must free the return value when done.
*
@@ -418,8 +405,8 @@ bla=bla
this_is = fdsafdas
bad_line=
reall bad line
reall bad line = again
really bad line
really bad line = again
5555= 55555
test = with lots of spaces
\endverbatim
@@ -449,83 +436,82 @@ this_is = fdsafdas
* @return 0 on success
* @see poptParseArgvString
*/
/*@-fcnuse@*/
int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
/*@globals fileSystem @*/
/*@modifies *fp, *argstrp, fileSystem @*/;
/*@=fcnuse@*/
int poptConfigFileToString(FILE *fp, char ** argstrp, int flags);
/** \ingroup popt
/**
* Return formatted error string for popt failure.
* @param error popt error
* @return error string
*/
/*@observer@*/
const char * poptStrerror(const int error)
/*@*/;
const char * poptStrerror(const int error);
/** \ingroup popt
/**
* Limit search for executables.
* @param con context
* @param path single path to search for executables
* @param allowAbsolute absolute paths only?
*/
/*@unused@*/
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
/*@modifies con @*/;
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
/** \ingroup popt
/**
* Print detailed description of options.
* @param con context
* @param fp ouput file handle
* @param fp output file handle
* @param flags (unused)
*/
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/;
void poptPrintHelp(poptContext con, FILE * fp, int flags);
/** \ingroup popt
/**
* Print terse description of options.
* @param con context
* @param fp ouput file handle
* @param fp output file handle
* @param flags (unused)
*/
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/;
void poptPrintUsage(poptContext con, FILE * fp, int flags);
/** \ingroup popt
/**
* Provide text to replace default "[OPTION...]" in help/usage output.
* @param con context
* @param text replacement text
*/
/*@-fcnuse@*/
void poptSetOtherOptionHelp(poptContext con, const char * text)
/*@modifies con @*/;
/*@=fcnuse@*/
void poptSetOtherOptionHelp(poptContext con, const char * text);
/** \ingroup popt
/**
* Return argv[0] from context.
* @param con context
* @return argv[0]
*/
/*@-fcnuse@*/
/*@observer@*/
const char * poptGetInvocationName(poptContext con)
/*@*/;
/*@=fcnuse@*/
const char * poptGetInvocationName(poptContext con);
/** \ingroup popt
/**
* Shuffle argv pointers to remove stripped args, returns new argc.
* @param con context
* @param argc no. of args
* @param argv arg vector
* @return new argc
*/
/*@-fcnuse@*/
int poptStrippedArgv(poptContext con, int argc, char ** argv)
/*@modifies *argv @*/;
/*@=fcnuse@*/
int poptStrippedArgv(poptContext con, int argc, char ** argv);
/**
* Add a string to an argv array.
* @retval *argvp argv array
* @param argInfo (unused)
* @param val string arg to add (using strdup)
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
int poptSaveString(const char *** argvp, unsigned int argInfo,
const char * val);
/**
* Save a long long, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg integer pointer, aligned on int boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLongLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
int poptSaveLongLong(long long * arg, unsigned int argInfo,
long long aLongLong);
/**
* Save a long, performing logical operation with value.
@@ -535,12 +521,17 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
/*@modifies *arg @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
int poptSaveLong(long * arg, unsigned int argInfo, long aLong);
/**
* Save a short integer, performing logical operation with value.
* @warning Alignment check may be too strict on certain platorms.
* @param arg short pointer, aligned on short boundary.
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
int poptSaveShort(short * arg, unsigned int argInfo, long aLong);
/**
* Save an integer, performing logical operation with value.
@@ -550,14 +541,40 @@ int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
* @param aLong value to use
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
/*@-incondefs@*/
/*@unused@*/
int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
/*@modifies *arg @*/
/*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
/*@=incondefs@*/
int poptSaveInt(int * arg, unsigned int argInfo, long aLong);
/* The bit set typedef. */
typedef struct poptBits_s {
unsigned int bits[1];
} * poptBits;
#define _POPT_BITS_N 1024U /*!< estimated population */
#define _POPT_BITS_M ((3U * _POPT_BITS_N) / 2U)
#define _POPT_BITS_K 16U /*!< no. of linear hash combinations */
extern unsigned int _poptBitsN;
extern unsigned int _poptBitsM;
extern unsigned int _poptBitsK;
int poptBitsAdd(poptBits bits, const char * s);
int poptBitsChk(poptBits bits, const char * s);
int poptBitsClr(poptBits bits);
int poptBitsDel(poptBits bits, const char * s);
int poptBitsIntersect(poptBits * ap, const poptBits b);
int poptBitsUnion(poptBits * ap, const poptBits b);
int poptBitsArgs(poptContext con, poptBits * ap);
/**
* Save a string into a bit set (experimental).
* @retval *bits bit set (lazily malloc'd if NULL)
* @param argInfo logical operation (see POPT_ARGFLAG_*)
* @param s string to add to bit set
* @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
*/
int poptSaveBits(poptBits * bitsp, unsigned int argInfo,
const char * s);
/*@=type@*/
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/** \ingroup popt
* \file popt/poptconfig.c
* @file
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
@@ -8,54 +8,300 @@
#include "system.h"
#include "poptint.h"
/*@access poptContext @*/
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static void configLine(poptContext con, char * line)
/*@modifies con @*/
#if defined(HAVE_FNMATCH_H)
#include <fnmatch.h>
#endif
#if defined(HAVE_GLOB_H)
#include <glob.h>
#if !defined(HAVE_GLOB_PATTERN_P)
/* Return nonzero if PATTERN contains any metacharacters.
Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
static int
glob_pattern_p (const char * pattern, int quote)
{
size_t nameLength;
const char * p;
int open = 0;
for (p = pattern; *p != '\0'; ++p)
switch (*p) {
case '?':
case '*':
return 1;
break;
case '\\':
if (quote && p[1] != '\0')
++p;
break;
case '[':
open = 1;
break;
case ']':
if (open)
return 1;
break;
}
return 0;
}
#endif /* !defined(__GLIBC__) */
static int poptGlobFlags = 0;
static int poptGlob_error(UNUSED(const char * epath),
UNUSED(int eerrno))
{
return 1;
}
#endif /* HAVE_GLOB_H */
/**
* Return path(s) from a glob pattern.
* @param con context
* @param pattern glob pattern
* @retval *acp no. of paths
* @retval *avp array of paths
* @return 0 on success
*/
static int poptGlob(UNUSED(poptContext con), const char * pattern,
int * acp, const char *** avp)
{
const char * pat = pattern;
int rc = 0; /* assume success */
#if defined(HAVE_GLOB_H)
if (glob_pattern_p(pat, 0)) {
glob_t _g, *pglob = &_g;
if (!(rc = glob(pat, poptGlobFlags, poptGlob_error, pglob))) {
if (acp) {
*acp = (int) pglob->gl_pathc;
pglob->gl_pathc = 0;
}
if (avp) {
*avp = (const char **) pglob->gl_pathv;
pglob->gl_pathv = NULL;
}
globfree(pglob);
} else if (rc == GLOB_NOMATCH) {
*avp = NULL;
*acp = 0;
rc = 0;
} else
rc = POPT_ERROR_ERRNO;
} else
#endif /* HAVE_GLOB_H */
{
if (acp)
*acp = 1;
if (avp && (*avp = calloc((size_t)(1 + 1), sizeof (**avp))) != NULL)
(*avp)[0] = xstrdup(pat);
}
return rc;
}
int poptSaneFile(const char * fn)
{
struct stat sb;
if (fn == NULL || strstr(fn, ".rpmnew") || strstr(fn, ".rpmsave"))
return 0;
if (stat(fn, &sb) == -1)
return 0;
if (!S_ISREG(sb.st_mode))
return 0;
if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
return 0;
return 1;
}
int poptReadFile(const char * fn, char ** bp, size_t * nbp, int flags)
{
int fdno;
char * b = NULL;
off_t nb = 0;
char * s, * t, * se;
int rc = POPT_ERROR_ERRNO; /* assume failure */
fdno = open(fn, O_RDONLY);
if (fdno < 0)
goto exit;
if ((nb = lseek(fdno, 0, SEEK_END)) == (off_t)-1
|| (uintmax_t)nb >= SIZE_MAX
|| lseek(fdno, 0, SEEK_SET) == (off_t)-1
|| (b = calloc(sizeof(*b), (size_t)nb + 1)) == NULL
|| read(fdno, (char *)b, (size_t)nb) != (ssize_t)nb)
{
int oerrno = errno;
(void) close(fdno);
if (nb != (off_t)-1 && (uintmax_t)nb >= SIZE_MAX)
errno = -EOVERFLOW;
else
errno = oerrno;
goto exit;
}
if (close(fdno) == -1)
goto exit;
if (b == NULL) {
rc = POPT_ERROR_MALLOC;
goto exit;
}
rc = 0;
/* Trim out escaped newlines. */
if (flags & POPT_READFILE_TRIMNEWLINES)
{
for (t = b, s = b, se = b + nb; *s && s < se; s++) {
switch (*s) {
case '\\':
if (s[1] == '\n') {
s++;
continue;
}
/* fallthrough */
default:
*t++ = *s;
break;
}
}
*t++ = '\0';
nb = (off_t)(t - b);
}
exit:
if (rc != 0) {
if (b)
free(b);
b = NULL;
nb = 0;
}
if (bp)
*bp = b;
else if (b)
free(b);
if (nbp)
*nbp = (size_t)nb;
return rc;
}
/**
* Check for application match.
* @param con context
* @param s config application name
* return 0 if config application matches
*/
static int configAppMatch(poptContext con, const char * s)
{
int rc = 1;
if (con->appName == NULL) /* XXX can't happen. */
return rc;
#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
if (glob_pattern_p(s, 1)) {
static int flags = FNM_PATHNAME | FNM_PERIOD;
#ifdef FNM_EXTMATCH
flags |= FNM_EXTMATCH;
#endif
rc = fnmatch(s, con->appName, flags);
} else
#endif
rc = strcmp(s, con->appName);
return rc;
}
static int poptConfigLine(poptContext con, char * line)
{
char *b = NULL;
size_t nb = 0;
char * se = line;
const char * appName;
const char * entryType;
const char * opt;
poptItem item = (poptItem) alloca(sizeof(*item));
struct poptItem_s item_buf;
poptItem item = &item_buf;
int i, j;
int rc = POPT_ERROR_BADCONFIG;
if (con->appName == NULL)
return;
nameLength = strlen(con->appName);
goto exit;
/*@-boundswrite@*/
memset(item, 0, sizeof(*item));
if (strncmp(line, con->appName, nameLength)) return;
appName = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (*se == '\0')
goto exit;
else
*se++ = '\0';
line += nameLength;
if (*line == '\0' || !isSpace(line)) return;
if (configAppMatch(con, appName)) goto exit;
while (*line != '\0' && isSpace(line)) line++;
entryType = line;
while (*line == '\0' || !isSpace(line)) line++;
*line++ = '\0';
while (*se != '\0' && _isspaceptr(se)) se++;
entryType = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (*se != '\0') *se++ = '\0';
while (*line != '\0' && isSpace(line)) line++;
if (*line == '\0') return;
opt = line;
while (*line == '\0' || !isSpace(line)) line++;
*line++ = '\0';
while (*se != '\0' && _isspaceptr(se)) se++;
if (*se == '\0') goto exit;
opt = se;
while (*se != '\0' && !_isspaceptr(se)) se++;
if (opt[0] == '-' && *se == '\0') goto exit;
if (*se != '\0') *se++ = '\0';
while (*line != '\0' && isSpace(line)) line++;
if (*line == '\0') return;
while (*se != '\0' && _isspaceptr(se)) se++;
if (opt[0] == '-' && *se == '\0') goto exit;
/*@-temptrans@*/ /* FIX: line alias is saved */
if (opt[0] == '-' && opt[1] == '-')
item->option.longName = opt + 2;
else if (opt[0] == '-' && opt[2] == '\0')
item->option.shortName = opt[1];
/*@=temptrans@*/
else {
const char * fn = opt;
if (poptParseArgvString(line, &item->argc, &item->argv)) return;
/* XXX handle globs and directories in fn? */
if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
goto exit;
if (b == NULL || nb == 0)
goto exit;
/* Append remaining text to the interpolated file option text. */
if (*se != '\0') {
size_t nse = strlen(se) + 1;
if ((b = realloc(b, (nb + nse))) == NULL) /* XXX can't happen */
goto exit;
(void) stpcpy( stpcpy(&b[nb-1], " "), se);
nb += nse;
}
se = b;
/* Use the basename of the path as the long option name. */
{ const char * longName = strrchr(fn, '/');
if (longName != NULL)
longName++;
else
longName = fn;
if (longName == NULL) /* XXX can't happen. */
goto exit;
/* Single character basenames are treated as short options. */
if (longName[1] != '\0')
item->option.longName = longName;
else
item->option.shortName = longName[0];
}
}
if (poptParseArgvString(se, &item->argc, &item->argv)) goto exit;
/*@-modobserver@*/
item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
for (i = 0, j = 0; i < item->argc; i++, j++) {
const char * f;
@@ -81,103 +327,183 @@ static void configLine(poptContext con, char * line)
item->argv[j] = NULL;
item->argc = j;
}
/*@=modobserver@*/
/*@=boundswrite@*/
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
if (!strcmp(entryType, "alias"))
(void) poptAddItem(con, item, 0);
rc = poptAddItem(con, item, 0);
else if (!strcmp(entryType, "exec"))
(void) poptAddItem(con, item, 1);
/*@=nullstate@*/
rc = poptAddItem(con, item, 1);
exit:
rc = 0; /* XXX for now, always return success */
if (b)
free(b);
return rc;
}
/*@=compmempass@*/
int poptReadConfigFile(poptContext con, const char * fn)
{
const char * file, * chptr, * end;
char * buf;
/*@dependent@*/ char * dst;
int fd, rc;
off_t fileLength;
fd = open(fn, O_RDONLY);
if (fd < 0)
return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
fileLength = lseek(fd, 0, SEEK_END);
if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
rc = errno;
(void) close(fd);
errno = rc;
return POPT_ERROR_ERRNO;
}
file = alloca(fileLength + 1);
if (read(fd, (char *)file, fileLength) != fileLength) {
rc = errno;
(void) close(fd);
errno = rc;
return POPT_ERROR_ERRNO;
}
if (close(fd) == -1)
return POPT_ERROR_ERRNO;
/*@-boundswrite@*/
dst = buf = alloca(fileLength + 1);
chptr = file;
end = (file + fileLength);
/*@-infloops@*/ /* LCL: can't detect chptr++ */
while (chptr < end) {
switch (*chptr) {
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isSpace(dst)) dst++;
if (*dst && *dst != '#')
configLine(con, dst);
chptr++;
/*@switchbreak@*/ break;
case '\\':
*dst++ = *chptr++;
if (chptr < end) {
if (*chptr == '\n')
dst--, chptr++;
/* \ at the end of a line does not insert a \n */
else
*dst++ = *chptr++;
}
/*@switchbreak@*/ break;
default:
*dst++ = *chptr++;
/*@switchbreak@*/ break;
}
}
/*@=infloops@*/
/*@=boundswrite@*/
return 0;
}
int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
{
char * fn, * home;
char * b = NULL, *be;
size_t nb = 0;
const char *se;
char *t = NULL, *te;
int rc;
if (con->appName == NULL) return 0;
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
if ((home = getenv("HOME"))) {
size_t bufsize = strlen(home) + 20;
fn = alloca(bufsize);
if (fn == NULL) return 0;
snprintf(fn, bufsize, "%s/.popt", home);
rc = poptReadConfigFile(con, fn);
if (rc) return rc;
if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
return (errno == ENOENT ? 0 : rc);
if (b == NULL || nb == 0) {
rc = POPT_ERROR_BADCONFIG;
goto exit;
}
return 0;
if ((t = malloc(nb + 1)) == NULL)
goto exit;
te = t;
be = (b + nb);
for (se = b; se < be; se++) {
switch (*se) {
case '\n':
*te = '\0';
te = t;
while (*te && _isspaceptr(te)) te++;
if (*te && *te != '#')
if ((rc = poptConfigLine(con, te)) != 0)
goto exit;
break;
case '\\':
*te = *se++;
/* \ at the end of a line does not insert a \n */
if (se < be && *se != '\n') {
te++;
*te++ = *se;
}
break;
default:
*te++ = *se;
break;
}
}
rc = 0;
exit:
free(t);
if (b)
free(b);
return rc;
}
int poptReadConfigFiles(poptContext con, const char * paths)
{
char * buf = (paths ? xstrdup(paths) : NULL);
const char * p;
char * pe;
int rc = 0; /* assume success */
for (p = buf; p != NULL && *p != '\0'; p = pe) {
const char ** av = NULL;
int ac = 0;
int i;
int xx;
/* locate start of next path element */
pe = strchr(p, ':');
if (pe != NULL && *pe == ':')
*pe++ = '\0';
else
pe = (char *) (p + strlen(p));
xx = poptGlob(con, p, &ac, &av);
/* work-off each resulting file from the path element */
for (i = 0; i < ac; i++) {
const char * fn = av[i];
if (!poptSaneFile(fn))
continue;
xx = poptReadConfigFile(con, fn);
if (xx && rc == 0)
rc = xx;
free((void *)av[i]);
av[i] = NULL;
}
free(av);
av = NULL;
}
if (buf)
free(buf);
return rc;
}
int poptReadDefaultConfig(poptContext con, UNUSED(int useEnv))
{
char * home;
struct stat sb;
int rc = 0; /* assume success */
if (con->appName == NULL) goto exit;
rc = poptReadConfigFile(con, POPT_SYSCONFDIR "/popt");
if (rc) goto exit;
#if defined(HAVE_GLOB_H)
if (!stat(POPT_SYSCONFDIR "/popt.d", &sb) && S_ISDIR(sb.st_mode)) {
const char ** av = NULL;
int ac = 0;
int i;
if ((rc = poptGlob(con, POPT_SYSCONFDIR "/popt.d/*", &ac, &av)) == 0) {
for (i = 0; rc == 0 && i < ac; i++) {
const char * fn = av[i];
if (!poptSaneFile(fn))
continue;
rc = poptReadConfigFile(con, fn);
free((void *)av[i]);
av[i] = NULL;
}
free(av);
av = NULL;
}
}
if (rc) goto exit;
#endif
if ((home = getenv("HOME"))) {
char * fn = malloc(strlen(home) + 20);
if (fn != NULL) {
(void) stpcpy(stpcpy(fn, home), "/.popt");
rc = poptReadConfigFile(con, fn);
free(fn);
} else
rc = POPT_ERROR_ERRNO;
if (rc) goto exit;
}
exit:
return rc;
}
poptContext
poptFini(poptContext con)
{
return poptFreeContext(con);
}
poptContext
poptInit(int argc, const char ** argv,
const struct poptOption * options, const char * configPaths)
{
poptContext con = NULL;
const char * argv0;
if (argv == NULL || argv[0] == NULL || options == NULL)
return con;
if ((argv0 = strrchr(argv[0], '/')) != NULL) argv0++;
else argv0 = argv[0];
con = poptGetContext(argv0, argc, (const char **)argv, options, 0);
if (con != NULL&& poptReadConfigFiles(con, configPaths))
con = poptFini(con);
return con;
}

View File

File diff suppressed because it is too large Load Diff

194
popt/poptint.c Normal file
View File

@@ -0,0 +1,194 @@
#include "system.h"
#include <stdarg.h>
#include <errno.h>
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#include "poptint.h"
/* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
#define _JLU3_jlu32lpair 1
#define jlu32lpair poptJlu32lpair
#include "lookup3.c"
const char *
POPT_prev_char (const char *str)
{
const char *p = str;
while (1) {
p--;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
return p;
}
}
const char *
POPT_next_char (const char *str)
{
const char *p = str;
while (*p != '\0') {
p++;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
break;
}
return p;
}
#if !defined(POPT_fprintf) /* XXX lose all the goop ... */
#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) && defined(HAVE_DCGETTEXT)
/*
* Rebind a "UTF-8" codeset for popt's internal use.
*/
char *
POPT_dgettext(const char * dom, const char * str)
{
char * codeset = NULL;
char * retval = NULL;
if (!dom)
dom = textdomain(NULL);
codeset = bind_textdomain_codeset(dom, NULL);
bind_textdomain_codeset(dom, "UTF-8");
retval = dgettext(dom, str);
bind_textdomain_codeset(dom, codeset);
return retval;
}
#endif
#ifdef HAVE_ICONV
/**
* Return malloc'd string converted from UTF-8 to current locale.
* @param istr input string (UTF-8 encoding assumed)
* @return localized string
*/
static char *
strdup_locale_from_utf8 (char * istr)
{
char * codeset = NULL;
char * ostr = NULL;
iconv_t cd;
if (istr == NULL)
return NULL;
#ifdef HAVE_LANGINFO_H
codeset = nl_langinfo ((nl_item)CODESET);
#endif
if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
&& (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
{
char * shift_pin = NULL;
size_t db = strlen(istr);
char * dstr = malloc((db + 1) * sizeof(*dstr));
char * dstr_tmp;
char * pin = istr;
char * pout = dstr;
size_t ib = db;
size_t ob = db;
size_t err;
if (dstr == NULL) {
(void) iconv_close(cd);
return NULL;
}
err = iconv(cd, NULL, NULL, NULL, NULL);
while (1) {
*pout = '\0';
err = iconv(cd, &pin, &ib, &pout, &ob);
if (err != (size_t)-1) {
if (shift_pin == NULL) {
shift_pin = pin;
pin = NULL;
ib = 0;
continue;
}
} else
switch (errno) {
case E2BIG:
{ size_t used = (size_t)(pout - dstr);
db *= 2;
dstr_tmp = realloc(dstr, (db + 1) * sizeof(*dstr));
if (dstr_tmp == NULL) {
free(dstr);
(void) iconv_close(cd);
return NULL;
}
dstr = dstr_tmp;
pout = dstr + used;
ob = db - used;
continue;
} break;
case EINVAL:
case EILSEQ:
default:
break;
}
break;
}
(void) iconv_close(cd);
*pout = '\0';
ostr = xstrdup(dstr);
free(dstr);
} else
ostr = xstrdup(istr);
return ostr;
}
#endif
int
POPT_fprintf (FILE * stream, const char * format, ...)
{
char * b = NULL, * ob = NULL;
int rc;
va_list ap;
#if defined(HAVE_VASPRINTF)
va_start(ap, format);
if ((rc = vasprintf(&b, format, ap)) < 0)
b = NULL;
va_end(ap);
#else
size_t nb = (size_t)1;
/* HACK: add +1 to the realloc no. of bytes "just in case". */
/* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
* to do with whether the final '\0' is counted (or not). The code
* below already adds +1 for the (possibly already counted) trailing NUL.
*/
while ((b = realloc(b, nb+1)) != NULL) {
va_start(ap, format);
rc = vsnprintf(b, nb, format, ap);
va_end(ap);
if (rc > -1) { /* glibc 2.1 */
if ((size_t)rc < nb)
break;
nb = (size_t)(rc + 1); /* precise buffer length known */
} else /* glibc 2.0 */
nb += (nb < (size_t)100 ? (size_t)100 : nb);
ob = b;
}
#endif
rc = 0;
if (b != NULL) {
#ifdef HAVE_ICONV
ob = strdup_locale_from_utf8(b);
if (ob != NULL) {
rc = fprintf(stream, "%s", ob);
free(ob);
} else
#endif
rc = fprintf(stream, "%s", b);
free (b);
}
return rc;
}
#endif /* !defined(POPT_fprintf) */

View File

@@ -1,5 +1,5 @@
/** \ingroup popt
* \file popt/poptint.h
* @file
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
@@ -9,108 +9,145 @@
#ifndef H_POPTINT
#define H_POPTINT
#include <stdint.h>
/**
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
* @param p memory to free
* @retval NULL always
*/
/*@unused@*/ static inline /*@null@*/ void *
_free(/*@only@*/ /*@null@*/ const void * p)
/*@modifies p @*/
static inline void *
_free(const void * p)
{
if (p != NULL) free((void *)p);
return NULL;
}
static inline int
isSpace(const char *ptr)
{
return isspace(*(unsigned char *)ptr);
}
/* Bit mask macros. */
/*@-exporttype -redef @*/
typedef unsigned int __pbm_bits;
/*@=exporttype =redef @*/
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
/*@-exporttype -redef @*/
typedef struct {
__pbm_bits bits[1];
} pbm_set;
/*@=exporttype =redef @*/
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(pbm_set))
#define PBM_FREE(s) _free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
extern void poptJlu32lpair(const void *key, size_t size,
uint32_t *pc, uint32_t *pb);
/** \ingroup popt
* Typedef's for string and array of strings.
*/
typedef const char * poptString;
typedef poptString * poptArgv;
/** \ingroup popt
* A union to simplify opt->arg access without casting.
*/
typedef union poptArg_u {
void * ptr;
int * intp;
short * shortp;
long * longp;
long long * longlongp;
float * floatp;
double * doublep;
const char ** argv;
poptCallbackType cb;
poptOption opt;
} poptArg;
extern unsigned int _poptArgMask;
extern unsigned int _poptGroupMask;
#define poptArgType(_opt) ((_opt)->argInfo & _poptArgMask)
#define poptGroup(_opt) ((_opt)->argInfo & _poptGroupMask)
#define F_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_ARGFLAG_##_FLAG)
#define LF_ISSET(_FLAG) (argInfo & POPT_ARGFLAG_##_FLAG)
#define CBF_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_CBFLAG_##_FLAG)
/* XXX sick hack to preserve pretense of a popt-1.x ABI. */
#define poptSubstituteHelpI18N(opt) \
{ if ((opt) == poptHelpOptions) (opt) = poptHelpOptionsI18N; }
struct optionStackEntry {
int argc;
/*@only@*/ /*@null@*/
const char ** argv;
/*@only@*/ /*@null@*/
poptArgv argv;
pbm_set * argb;
int next;
/*@only@*/ /*@null@*/
const char * nextArg;
/*@observer@*/ /*@null@*/
char * nextArg;
const char * nextCharArg;
/*@dependent@*/ /*@null@*/
poptItem currAlias;
int stuffed;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/
struct optionStackEntry * os;
/*@owned@*/ /*@null@*/
const char ** leftovers;
poptArgv leftovers;
int numLeftovers;
int allocLeftovers;
int nextLeftover;
/*@keep@*/
const struct poptOption * options;
int restLeftover;
/*@only@*/ /*@null@*/
const char * appName;
/*@only@*/ /*@null@*/
poptItem aliases;
int numAliases;
int flags;
/*@owned@*/ /*@null@*/
unsigned int flags;
poptItem execs;
int numExecs;
/*@only@*/ /*@null@*/
const char ** finalArgv;
char * execFail;
poptArgv finalArgv;
int finalArgvCount;
int finalArgvAlloced;
/*@dependent@*/ /*@null@*/
int (*maincall) (int argc, const char **argv);
poptItem doExec;
/*@only@*/
const char * execPath;
int execAbsolute;
/*@only@*/ /*@relnull@*/
const char * otherHelp;
/*@null@*/
pbm_set * arg_strip;
};
#ifdef HAVE_LIBINTL_H
#if defined(POPT_fprintf)
#define POPT_dgettext dgettext
#else
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#if defined(HAVE_DCGETTEXT)
char *POPT_dgettext(const char * dom, const char * str);
#endif
FORMAT(printf, 2, 3)
int POPT_fprintf (FILE* stream, const char *format, ...);
#endif /* !defined(POPT_fprintf) */
const char *POPT_prev_char (const char *str);
const char *POPT_next_char (const char *str);
#endif
#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H)
#include <libintl.h>
#endif
#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
#define _(foo) gettext(foo)
#else
#define _(foo) foo
#endif
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) dgettext(dom, str)
#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) && defined(HAVE_DCGETTEXT)
#define D_(dom, str) POPT_dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else
#define D_(dom, str) str
@@ -119,4 +156,3 @@ struct poptContext_s {
#define N_(foo) foo
#endif

View File

@@ -1,5 +1,5 @@
/** \ingroup popt
* \file popt/poptparse.c
* @file
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
@@ -8,11 +8,8 @@
#include "system.h"
#include "poptint.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5
/*@-boundswrite@*/
int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr)
{
@@ -34,13 +31,13 @@ int poptDupArgv(int argc, const char **argv,
return POPT_ERROR_MALLOC;
argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv);
*dst = '\0';
/*@-branchstate@*/
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst += strlcpy(dst, argv[i], nb) + 1;
dst = stpcpy(dst, argv[i]);
dst++; /* trailing NUL */
}
/*@=branchstate@*/
argv2[argc] = NULL;
if (argvPtr) {
@@ -53,21 +50,25 @@ int poptDupArgv(int argc, const char **argv,
*argcPtr = argc;
return 0;
}
/*@=boundswrite@*/
/*@-bounds@*/
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{
const char * src;
char quote = '\0';
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
const char ** argv_tmp;
int argc = 0;
int buflen = strlen(s) + 1;
char * buf = memset(alloca(buflen), 0, buflen);
size_t buflen = strlen(s) + 1;
char * buf, * bufOrig = NULL;
int rc = POPT_ERROR_MALLOC;
if (argv == NULL) return rc;
buf = bufOrig = calloc((size_t)1, buflen);
if (buf == NULL) {
free(argv);
return rc;
}
argv[argc] = buf;
for (src = s; *src != '\0'; src++) {
@@ -83,13 +84,14 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isSpace(src)) {
} else if (_isspaceptr(src)) {
if (*argv[argc] != '\0') {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
if (argv == NULL) goto exit;
argv_tmp = realloc(argv, sizeof(*argv) * argvAlloced);
if (argv_tmp == NULL) goto exit;
argv = argv_tmp;
}
argv[argc] = buf;
}
@@ -97,17 +99,17 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
case '"':
case '\'':
quote = *src;
/*@switchbreak@*/ break;
break;
case '\\':
src++;
if (!*src) {
rc = POPT_ERROR_BADQUOTE;
goto exit;
}
/*@fallthrough@*/
/* fallthrough */
default:
*buf++ = *src;
/*@switchbreak@*/ break;
break;
}
}
@@ -118,29 +120,30 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
exit:
if (bufOrig) free(bufOrig);
if (argv) free(argv);
return rc;
}
/*@=bounds@*/
/* still in the dev stage.
* return values, perhaps 1== file erro
* return values, perhaps 1== file error
* 2== line to long
* 3== umm.... more?
*/
int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
int poptConfigFileToString(FILE *fp, char ** argstrp,
UNUSED(int flags))
{
char line[999];
char * argstr;
char * argstr_tmp;
char * p;
char * q;
char * x;
int t;
int argvlen = 0;
size_t t;
size_t argvlen = 0;
size_t maxlinelen = sizeof(line);
size_t linelen;
int maxargvlen = 480;
int linenum = 0;
size_t maxargvlen = (size_t)480;
*argstrp = NULL;
@@ -155,11 +158,10 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
if (argstr == NULL) return POPT_ERROR_MALLOC;
while (fgets(line, (int)maxlinelen, fp) != NULL) {
linenum++;
p = line;
/* loop until first non-space char or EOL */
while( *p != '\0' && isSpace(p) )
while( *p != '\0' && _isspaceptr(p) )
p++;
linelen = strlen(p);
@@ -173,25 +175,29 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
q = p;
while (*q != '\0' && (!isSpace(q)) && *q != '=')
while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
q++;
if (isSpace(q)) {
if (_isspaceptr(q)) {
/* a space after the name, find next non space */
*q++='\0';
while( *q != '\0' && isSpace(q) ) q++;
while( *q != '\0' && _isspaceptr(q) ) q++;
}
if (*q == '\0') {
/* single command line option (ie, no name=val, just name) */
q[-1] = '\0'; /* kill off newline from fgets() call */
argvlen += (t = q - p) + (sizeof(" --")-1);
argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
argstr_tmp = realloc(argstr, maxargvlen);
if (argstr_tmp == NULL) {
free(argstr);
return POPT_ERROR_MALLOC;
}
argstr = argstr_tmp;
}
strlcat(argstr, " --", maxargvlen);
strlcat(argstr, p, maxargvlen);
strcat(argstr, " --");
strcat(argstr, p);
continue;
}
if (*q != '=')
@@ -201,29 +207,33 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
*q++ = '\0';
/* find next non-space letter of value */
while (*q != '\0' && isSpace(q))
while (*q != '\0' && _isspaceptr(q))
q++;
if (*q == '\0')
continue; /* XXX silently ignore missing value */
/* now, loop and strip all ending whitespace */
x = p + linelen;
while (isSpace(--x))
*x = 0; /* null out last char if space (including fgets() NL) */
while (_isspaceptr(--x))
*x = '\0'; /* null out last char if space (including fgets() NL) */
/* rest of line accept */
t = x - p;
t = (size_t)(x - p);
argvlen += t + (sizeof("' --='")-1);
if (argvlen >= maxargvlen) {
maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
argstr = realloc(argstr, maxargvlen);
if (argstr == NULL) return POPT_ERROR_MALLOC;
argstr_tmp = realloc(argstr, maxargvlen);
if (argstr_tmp == NULL) {
free(argstr);
return POPT_ERROR_MALLOC;
}
argstr = argstr_tmp;
}
strlcat(argstr, " --", maxargvlen);
strlcat(argstr, p, maxargvlen);
strlcat(argstr, "=\"", maxargvlen);
strlcat(argstr, q, maxargvlen);
strlcat(argstr, "\"", maxargvlen);
strcat(argstr, " --");
strcat(argstr, p);
strcat(argstr, "=\"");
strcat(argstr, q);
strcat(argstr, "\"");
}
*argstrp = argstr;

View File

@@ -1,134 +1,70 @@
/**
* @file
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined (__GLIBC__) && defined(__LCLINT__)
/*@-declundef@*/
/*@unchecked@*/
extern __const __int32_t *__ctype_tolower;
/*@unchecked@*/
extern __const __int32_t *__ctype_toupper;
/*@=declundef@*/
#endif
#ifdef __TANDEM
# include <floss.h(floss_execvp,floss_read)>
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
/* XXX isspace(3) has i18n encoding signedness issues on Solaris. */
#define _isspaceptr(_chp) isspace((int)(*(unsigned const char *)(_chp)))
#if HAVE_MCHECK_H
#ifdef HAVE_MCHECK_H
#include <mcheck.h>
#endif
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef __GNUC__
#define __attribute__(x)
#endif
void * xmalloc (size_t size);
#ifdef __NeXT
/* access macros are not declared in non posix mode in unistd.h -
don't try to use posix on NeXTstep 3.3 ! */
#include <libc.h>
#endif
void * xcalloc (size_t nmemb, size_t size);
#if defined(__LCLINT__)
/*@-declundef -incondefs @*/ /* LCL: missing annotation */
/*@only@*/ /*@out@*/
void * alloca (size_t __size)
/*@ensures MaxSet(result) == (__size - 1) @*/
/*@*/;
/*@=declundef =incondefs @*/
#endif
void * xrealloc (void * ptr, size_t size);
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifdef HAVE_ALLOCA
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca(size_t size);
# endif
# else
# ifdef alloca
# undef alloca
# endif
# define alloca(sz) malloc(sz) /* Kludge this for now */
# endif
# endif
# endif
#elif !defined(alloca)
#define alloca __builtin_alloca
#endif
char * xstrdup (const char *str);
#ifndef HAVE_STRLCPY
size_t strlcpy(char *d, const char *s, size_t bufsize);
#endif
#if !defined(HAVE_STPCPY)
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
static inline char * stpcpy (char *dest, const char * src) {
register char *d = dest;
register const char *s = src;
#ifndef HAVE_STRLCAT
size_t strlcat(char *d, const char *s, size_t bufsize);
#endif
#if HAVE_MCHECK_H && defined(__GNUC__)
static inline char *
xstrdup(const char *s)
{
size_t memsize = strlen(s) + 1;
char *ptr = malloc(memsize);
if (!ptr) {
fprintf(stderr, "virtual memory exhausted.\n");
exit(EXIT_FAILURE);
}
strlcpy(ptr, s, memsize);
return ptr;
do
*d++ = *s;
while (*s++ != '\0');
return d - 1;
}
#else
#define xstrdup(_str) strdup(_str)
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
#endif
#if HAVE___SECURE_GETENV && !defined(__LCLINT__)
/* Memory allocation via macro defs to get meaningful locations from mtrace() */
#if defined(HAVE_MCHECK_H) && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
#define xmalloc(_size) (malloc(_size) ? : vmefail())
#define xcalloc(_nmemb, _size) (calloc((_nmemb), (_size)) ? : vmefail())
#define xrealloc(_ptr, _size) (realloc((_ptr), (_size)) ? : vmefail())
#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str)))
#else
#define xmalloc(_size) malloc(_size)
#define xcalloc(_nmemb, _size) calloc((_nmemb), (_size))
#define xrealloc(_ptr, _size) realloc((_ptr), (_size))
#define xstrdup(_str) strdup(_str)
#endif /* defined(HAVE_MCHECK_H) && defined(__GNUC__) */
#if defined(HAVE_SECURE_GETENV)
#define getenv(_s) secure_getenv(_s)
#elif defined(HAVE___SECURE_GETENV)
#define getenv(_s) __secure_getenv(_s)
#endif
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
#define snprintf rsync_snprintf
int snprintf(char *str,size_t count,const char *fmt,...);
#if !defined(__GNUC__) && !defined(__attribute__)
#define __attribute__(x)
#endif
#define UNUSED(x) x __attribute__((__unused__))
#define PACKAGE "rsync"
#define FORMAT(a, b, c) __attribute__((__format__ (a, b, c)))
#define NORETURN __attribute__((__noreturn__))
#include "popt.h"