From 5d0641a49aa3545f73b6fdefb388923018512597 Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 18 Jan 2009 21:51:47 -0500 Subject: [PATCH] Sync libc/stdlib with FreeBSD (ignoring jemalloc, pts, and gdtoa): -Add a64l(), l64a(), and l64a_r() XSI extentions. These functions convert between a 32-bit integer and a radix-64 ASCII string. -Replace some syscalls with libc version. -Remove advertising clause. -alloca() cannot check if the allocation is valid; mention the consequences. -Include some verbage about not calling exit() from functions registered by atexit(). -Use pthread mutexes where possible instead of libc spinlocks. -Significantly reduce the memory leak as noted in the BUGS section of setenv(3) by tracking the size of the memory allocated instead of using strlen() on the current value. -Prefer setenv() instead of putenv(). -Convert *env() calls to POSIX: -unsetenv returns an int. -putenv takes a char * instead of const char *. -putenv no longer makes a copy of the input string. -errno is set appropriately. Exceptions involve bad environ variable and internal initialization code. These both set errno to EFAULT. -Make getopt_long() more GNU compatible and sync up with OpenBSD's version. -POSIX clearly states that getsubopt() should be declared in not in -Use size_t to avoid overflow when sorting arrays larger than 2 GB in heapsort() and qsort(). -Add new implementations of insque() and remque() which conform to IEEE Std 1003.1-2001. -Add qsort_r() for functions that need to be reentrant. -Improve radixsort()'s preformance when sorting strings with common prefixes. -Use 'uint32_t' instead of 'long' when a 32-bit integer is intended in random(3). -Rearrange in a more logical order based on visibility. -Move getsubopt()'s prototype to (standards). -Make an internal _getprogname() that is used only inside libc. For libc, getprogname(3) is a weak symbol in case a function of the same name is defined in userland. --- bin/df/df.c | 16 +- bin/sh/var.c | 33 +- include/search.h | 128 +++---- include/stdlib.h | 219 ++++++++---- include/unistd.h | 3 - lib/libc/gen/getprogname.c | 11 +- lib/libc/include/libc_private.h | 11 + lib/libc/stdlib/Makefile.inc | 38 +- lib/libc/stdlib/a64l.3 | 187 ++++++++++ lib/libc/stdlib/a64l.c | 34 ++ lib/libc/stdlib/abort.3 | 13 +- lib/libc/stdlib/abort.c | 37 +- lib/libc/stdlib/abs.3 | 12 +- lib/libc/stdlib/abs.c | 5 +- lib/libc/stdlib/alloca.3 | 39 +- lib/libc/stdlib/atexit.3 | 24 +- lib/libc/stdlib/atexit.c | 51 ++- lib/libc/stdlib/atexit.h | 7 +- lib/libc/stdlib/atof.3 | 35 +- lib/libc/stdlib/atof.c | 8 +- lib/libc/stdlib/atoi.3 | 27 +- lib/libc/stdlib/atoi.c | 6 +- lib/libc/stdlib/atol.3 | 9 +- lib/libc/stdlib/atol.c | 6 +- lib/libc/stdlib/bsearch.3 | 6 +- lib/libc/stdlib/bsearch.c | 7 +- lib/libc/stdlib/div.3 | 16 +- lib/libc/stdlib/div.c | 5 +- lib/libc/stdlib/exit.3 | 60 ++-- lib/libc/stdlib/exit.c | 16 +- lib/libc/stdlib/getenv.3 | 160 ++++++--- lib/libc/stdlib/getenv.c | 772 +++++++++++++++++++++++++++++++++++----- lib/libc/stdlib/getopt.3 | 107 ++++-- lib/libc/stdlib/getopt.c | 14 +- lib/libc/stdlib/getopt_long.3 | 508 +++++++++++++++++--------- lib/libc/stdlib/getopt_long.c | 608 +++++++++++++++++++------------ lib/libc/stdlib/getsubopt.3 | 8 +- lib/libc/stdlib/getsubopt.c | 11 +- lib/libc/stdlib/hcreate.3 | 40 ++- lib/libc/stdlib/hcreate.c | 10 +- lib/libc/stdlib/heapsort.c | 10 +- lib/libc/stdlib/insque.3 | 61 ++++ lib/libc/stdlib/insque.c | 47 +++ lib/libc/stdlib/l64a.c | 40 +++ lib/libc/stdlib/labs.3 | 10 +- lib/libc/stdlib/labs.c | 5 +- lib/libc/stdlib/ldiv.3 | 20 +- lib/libc/stdlib/ldiv.c | 5 +- lib/libc/stdlib/lsearch.c | 2 +- lib/libc/stdlib/malloc.c | 2 - lib/libc/stdlib/memory.3 | 16 +- lib/libc/stdlib/merge.c | 7 +- lib/libc/stdlib/putenv.c | 56 --- lib/libc/stdlib/qsort.3 | 112 ++++-- lib/libc/stdlib/qsort.c | 70 ++-- lib/libc/stdlib/qsort_r.c | 8 + lib/libc/stdlib/radixsort.3 | 14 +- lib/libc/stdlib/radixsort.c | 28 +- lib/libc/stdlib/rand.3 | 12 +- lib/libc/stdlib/rand.c | 19 +- lib/libc/stdlib/random.3 | 25 +- lib/libc/stdlib/random.c | 70 ++-- lib/libc/stdlib/realpath.3 | 16 +- lib/libc/stdlib/realpath.c | 2 +- lib/libc/stdlib/remque.c | 30 ++ lib/libc/stdlib/setenv.c | 114 ------ lib/libc/stdlib/strtol.3 | 12 +- lib/libc/stdlib/strtoq.c | 9 +- lib/libc/stdlib/strtoul.3 | 13 +- lib/libc/stdlib/strtouq.c | 9 +- lib/libc/stdlib/system.3 | 10 +- lib/libc/stdlib/system.c | 11 +- lib/libc/stdlib/tdelete.c | 19 +- lib/libc/stdlib/tfind.c | 11 +- lib/libc/stdlib/tsearch.3 | 40 ++- lib/libc/stdlib/tsearch.c | 9 +- lib/libc/stdlib/twalk.c | 15 +- libexec/pppoed/pppoed.c | 8 +- usr.bin/du/du.c | 8 +- usr.bin/env/env.c | 6 +- usr.bin/limits/limits.c | 6 +- usr.sbin/pstat/pstat.c | 4 +- 82 files changed, 2860 insertions(+), 1438 deletions(-) rewrite include/search.h (63%) create mode 100644 lib/libc/stdlib/a64l.3 create mode 100644 lib/libc/stdlib/a64l.c rewrite lib/libc/stdlib/getenv.c (71%) create mode 100644 lib/libc/stdlib/insque.3 create mode 100644 lib/libc/stdlib/insque.c create mode 100644 lib/libc/stdlib/l64a.c delete mode 100644 lib/libc/stdlib/putenv.c create mode 100644 lib/libc/stdlib/qsort_r.c create mode 100644 lib/libc/stdlib/remque.c delete mode 100644 lib/libc/stdlib/setenv.c diff --git a/bin/df/df.c b/bin/df/df.c index 5a6025e2c5..af6264864b 100644 --- a/bin/df/df.c +++ b/bin/df/df.c @@ -128,13 +128,13 @@ main(int argc, char **argv) case 'b': /* FALLTHROUGH */ case 'P': - if (putenv("BLOCKSIZE=512") != 0) - warn("putenv: cannot set BLOCKSIZE=512"); + if (setenv("BLOCKSIZE", "512", 1) != 0) + warn("setenv: cannot set BLOCKSIZE=512"); hflag = 0; break; case 'g': - if (putenv("BLOCKSIZE=1g") != 0) - warn("putenv: cannot set BLOCKSIZE=1g"); + if (setenv("BLOCKSIZE", "1g", 1) != 0) + warn("setenv: cannot set BLOCKSIZE=1g"); hflag = 0; break; case 'H': @@ -147,8 +147,8 @@ main(int argc, char **argv) iflag = 1; break; case 'k': - if (putenv("BLOCKSIZE=1k") != 0) - warn("putenv: cannot set BLOCKSIZE=1k"); + if (setenv("BLOCKSIZE", "1k", 1) != 0) + warn("setenv: cannot set BLOCKSIZE=1k"); hflag = 0; break; case 'l': @@ -157,8 +157,8 @@ main(int argc, char **argv) vfslist = makevfslist(makenetvfslist()); break; case 'm': - if (putenv("BLOCKSIZE=1m") != 0) - warn("putenv: cannot set BLOCKSIZE=1m"); + if (setenv("BLOCKSIZE", "1m", 1) != 0) + warn("setenv: cannot set BLOCKSIZE=1m"); hflag = 0; break; case 'n': diff --git a/bin/sh/var.c b/bin/sh/var.c index bb87eb00fa..e78d67b07d 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -281,6 +281,28 @@ localevar(const char *s) } /* + * Sets/unsets an environment variable from a pointer that may actually be a + * pointer into environ where the string should not be manipulated. + */ +static void +change_env(char *s, int set) +{ + char *eqp; + char *ss; + + ss = savestr(s); + if ((eqp = strchr(ss, '=')) != NULL) + *eqp = '\0'; + if (set && eqp != NULL) { + if (setenv(ss, eqp + 1, 1) != 0) + error("setenv: cannot set %s=%s", ss, eqp + 1); + } else + unsetenv(ss); + ckfree(ss); +} + + +/* * Same as setvar except that the variable and value are passed in * the first argument as name=value. Since the first argument will * be actually stored in the table, it should not be a string that @@ -321,8 +343,7 @@ setvareq(char *s, int flags) if (vp == &vmpath || (vp == &vmail && ! mpathset())) chkmail(1); if ((vp->flags & VEXPORT) && localevar(s)) { - if (putenv(s) != 0) - error("putenv: cannot set %s", s); + change_env(s, 1); setlocale(LC_ALL, ""); } INTON; @@ -338,8 +359,7 @@ setvareq(char *s, int flags) INTOFF; *vpp = vp; if ((vp->flags & VEXPORT) && localevar(s)) { - if (putenv(s) != 0) - error("putenv: cannot set %s", s); + change_env(s, 1); setlocale(LC_ALL, ""); } INTON; @@ -600,8 +620,7 @@ exportcmd(int argc, char **argv) vp->flags |= flag; if ((vp->flags & VEXPORT) && localevar(vp->text)) { - if (putenv(vp->text) != 0) - error("putenv: cannot set %s", vp->text); + change_env(vp->text, 1); setlocale(LC_ALL, ""); } goto found; @@ -793,7 +812,7 @@ unsetvar(const char *s) if (*(strchr(vp->text, '=') + 1) != '\0') setvar(s, nullstr, 0); if ((vp->flags & VEXPORT) && localevar(vp->text)) { - unsetenv(s); + change_env(s, 0); setlocale(LC_ALL, ""); } vp->flags &= ~VEXPORT; diff --git a/include/search.h b/include/search.h dissimilarity index 63% index ccd7427d48..1e9b99c51f 100644 --- a/include/search.h +++ b/include/search.h @@ -1,61 +1,67 @@ -/* $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ */ -/* $FreeBSD: src/include/search.h,v 1.3.2.1 2000/08/17 07:38:34 jhb Exp $ */ -/* $DragonFly: src/include/search.h,v 1.6 2008/05/19 10:05:18 corecode Exp $ */ - -/* - * Written by J.T. Conklin - * Public domain. - */ - -#ifndef _SEARCH_H_ -#define _SEARCH_H_ - -#include -#include - -#ifndef _SIZE_T_DECLARED -#define _SIZE_T_DECLARED -typedef __size_t size_t; -#endif - -typedef struct entry { - char *key; - void *data; -} ENTRY; - -typedef enum { - FIND, ENTER -} ACTION; - -typedef enum { - preorder, - postorder, - endorder, - leaf -} VISIT; - -#ifdef _SEARCH_PRIVATE -typedef struct node { - char *key; - struct node *llink, *rlink; -} node_t; -#endif - -__BEGIN_DECLS -int hcreate (size_t); -void hdestroy (void); -ENTRY *hsearch (ENTRY, ACTION); -void *lfind(const void *, const void *, size_t *, size_t, - int (*)(const void *, const void *)); -void *lsearch(const void *, void *, size_t *, size_t, - int (*)(const void *, const void *)); -void *tdelete (const void *, void **, - int (*)(const void *, const void *)); -void *tfind (const void *, void **, - int (*)(const void *, const void *)); -void *tsearch (const void *, void **, - int (*)(const void *, const void *)); -void twalk (const void *, void (*)(const void *, VISIT, int)); -__END_DECLS - -#endif /* !_SEARCH_H_ */ +/*- + * Written by J.T. Conklin + * Public domain. + * + * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ + * $FreeBSD: src/include/search.h,v 1.10 2002/10/16 14:29:23 robert Exp $ + * $DragonFly: src/include/search.h,v 1.6 2008/05/19 10:05:18 corecode Exp $ + */ + +#ifndef _SEARCH_H_ +#define _SEARCH_H_ + +#include +#include + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + +typedef struct entry { + char *key; + void *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +typedef enum { + preorder, + postorder, + endorder, + leaf +} VISIT; + +#ifdef _SEARCH_PRIVATE +typedef struct node { + char *key; + struct node *llink, *rlink; +} node_t; + +struct que_elem { + struct que_elem *next; + struct que_elem *prev; +}; +#endif + +__BEGIN_DECLS +int hcreate(size_t); +void hdestroy(void); +ENTRY *hsearch(ENTRY, ACTION); +void insque(void *, void *); +void *lfind(const void *, const void *, size_t *, size_t, + int (*)(const void *, const void *)); +void *lsearch(const void *, void *, size_t *, size_t, + int (*)(const void *, const void *)); +void remque(void *); +void *tdelete(const void * __restrict, void ** __restrict, + int (*)(const void *, const void *)); +void *tfind(const void *, void * const *, + int (*)(const void *, const void *)); +void *tsearch(const void *, void **, int (*)(const void *, const void *)); +void twalk(const void *, void (*)(const void *, VISIT, int)); +__END_DECLS + +#endif /* !_SEARCH_H_ */ diff --git a/include/stdlib.h b/include/stdlib.h index 6f54500cdf..7f717c0081 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 - * $FreeBSD: src/include/stdlib.h,v 1.16.2.5 2002/12/13 01:34:00 tjr Exp $ + * $FreeBSD: src/include/stdlib.h,v 1.67 2008/07/22 11:40:42 ache Exp $ * $DragonFly: src/include/stdlib.h,v 1.22 2008/06/05 17:53:10 swildner Exp $ */ @@ -39,43 +39,31 @@ #define _STDLIB_H_ #include +#include #include -#ifndef _SYS_STDINT_H_ -#include +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED #endif -#ifndef __cplusplus +#ifndef __cplusplus #ifndef _WCHAR_T_DECLARED -#define _WCHAR_T_DECLARED -typedef __wchar_t wchar_t; +typedef __wchar_t wchar_t; +#define _WCHAR_T_DECLARED #endif #endif -#ifndef _SIZE_T_DECLARED -#define _SIZE_T_DECLARED -typedef __size_t size_t; -#endif - typedef struct { - int quot; /* quotient */ - int rem; /* remainder */ + int quot; /* quotient */ + int rem; /* remainder */ } div_t; typedef struct { - long quot; /* quotient */ - long rem; /* remainder */ + long quot; + long rem; } ldiv_t; -#if __ISO_C_VISIBLE >= 1999 -typedef struct { - long long quot; - long long rem; -} lldiv_t; -#endif - -#include - #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 @@ -85,8 +73,8 @@ extern int __mb_cur_max; #define MB_CUR_MAX __mb_cur_max __BEGIN_DECLS -void _Exit(int) __dead2; void abort(void) __dead2; +/* void abort2(const char *, int, void **) __dead2; */ int abs(int) __pure2; int atexit(void (*)(void)); double atof(const char *); @@ -101,54 +89,146 @@ void free(void *); char *getenv(const char *); long labs(long) __pure2; ldiv_t ldiv(long, long) __pure2; -#if __ISO_C_VISIBLE >= 1999 -lldiv_t lldiv(long long, long long) __pure2; -#endif void *malloc(size_t); -void qsort(void *, size_t, size_t, int(*)(const void *, const void *)); +int mblen(const char *, size_t); +size_t mbstowcs(wchar_t * __restrict , const char * __restrict, size_t); +int mbtowc(wchar_t * __restrict, const char * __restrict, size_t); +void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); int rand(void); void *realloc(void *, size_t); void srand(unsigned); -double strtod(const char *, char **); -#ifdef __LONG_LONG_SUPPORTED -long long int atoll(const char *); -long long llabs(long long) __pure2; -long long strtoll(const char *, char **, int); -unsigned long long strtoull(const char *, char **, int); +double strtod(const char * __restrict, char ** __restrict); +/* float strtof(const char * __restrict, char ** __restrict); */ +#if !defined(_KERNEL_VIRTUAL) +long strtol(const char * __restrict, char ** __restrict, int); #endif -int system(const char *); - +/* long double + strtold(const char * __restrict, char ** __restrict); */ #if !defined(_KERNEL_VIRTUAL) -long strtol(const char *, char **, int); -unsigned long strtoul(const char *, char **, int); +unsigned long + strtoul(const char * __restrict, char ** __restrict, int); #endif - -int mblen(const char *, size_t); -size_t mbstowcs(wchar_t *, const char *, size_t); +int system(const char *); int wctomb(char *, wchar_t); -int mbtowc(wchar_t *, const char *, size_t); -size_t wcstombs(char *, const wchar_t *, size_t); +size_t wcstombs(char * __restrict, const wchar_t * __restrict, size_t); + +/* + * Functions added in C99 which we make conditionally available in the + * BSD^C89 namespace if the compiler supports `long long'. + * The #if test is more complicated than it ought to be because + * __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long' + * is not supported in the compilation environment (which therefore means + * that it can't really be ISO C99). + * + * (The only other extension made by C99 in this header is _Exit().) + */ +#if __ISO_C_VISIBLE >= 1999 +#ifdef __LONG_LONG_SUPPORTED +/* LONGLONG */ +typedef struct { + long long quot; + long long rem; +} lldiv_t; -#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) -int putenv(const char *); +/* LONGLONG */ +long long + atoll(const char *); +/* LONGLONG */ +long long + llabs(long long) __pure2; +/* LONGLONG */ +lldiv_t lldiv(long long, long long) __pure2; +/* LONGLONG */ +long long + strtoll(const char * __restrict, char ** __restrict, int); +/* LONGLONG */ +unsigned long long + strtoull(const char * __restrict, char ** __restrict, int); +#endif /* __LONG_LONG_SUPPORTED */ + +void _Exit(int) __dead2; +#endif /* __ISO_C_VISIBLE >= 1999 */ + +/* + * Extensions made by POSIX relative to C. We don't know yet which edition + * of POSIX made these extensions, so assume they've always been there until + * research can be done. + */ +#if __POSIX_VISIBLE /* >= ??? */ +/*int posix_memalign(void **, size_t, size_t); (ADV) */ +int rand_r(unsigned *); /* (TSF) */ int setenv(const char *, const char *, int); +int unsetenv(const char *); +#endif +/* + * The only changes to the XSI namespace in revision 6 were the deletion + * of the ttyslot() and valloc() functions, which we never declared + * in this header. For revision 7, ecvt(), fcvt(), and gcvt(), which + * we also do not have, and mktemp(), are to be deleted. + */ +#if __XSI_VISIBLE +/* XXX XSI requires pollution from here. We'd rather not. */ +long a64l(const char *); double drand48(void); +/* char *ecvt(double, int, int * __restrict, int * __restrict); */ double erand48(unsigned short[3]); +/* char *fcvt(double, int, int * __restrict, int * __restrict); */ +/* char *gcvt(double, int, int * __restrict, int * __restrict); */ +int getsubopt(char **, char *const *, char **); +int grantpt(int); +char *initstate(unsigned long /* XSI requires u_int */, char *, long); long jrand48(unsigned short[3]); +char *l64a(long); void lcong48(unsigned short[7]); long lrand48(void); +int mkstemp(char *); long mrand48(void); long nrand48(unsigned short[3]); -unsigned short *seed48(unsigned short[3]); +/* int posix_openpt(int); */ +/* char *ptsname(int); */ +int putenv(char *); +long random(void); +char *realpath(const char *, char resolved_path[]); +unsigned short + *seed48(unsigned short[3]); +int setkey(const char *); +char *setstate(/* const */ char *); void srand48(long); +void srandom(unsigned long); +/* int unlockpt(int); */ +#endif /* __XSI_VISIBLE */ -void *alloca(size_t); /* built-in for gcc */ - /* getcap(3) functions */ -__uint32_t arc4random(void); +#if __BSD_VISIBLE +/* extern const char *_malloc_options; +extern void (*_malloc_message)(const char *, const char *, const char *, + const char *); */ + +/* + * The alloca() function can't be implemented in C, and on some + * platforms it can't be implemented at all as a callable function. + * The GNU C compiler provides a built-in alloca() which we can use; + * in all other cases, provide a prototype, mainly to pacify various + * incarnations of lint. On platforms where alloca() is not in libc, + * programs which use it will fail to link when compiled with non-GNU + * compilers. + */ +#if __GNUC__ >= 2 || defined(__INTEL_COMPILER) +#undef alloca /* some GNU bits try to get cute and define this on their own */ +#define alloca(sz) __builtin_alloca(sz) +#elif defined(lint) +void *alloca(size_t); +#endif + +__uint32_t + arc4random(void); void arc4random_addrandom(__uint8_t *, size_t); +void arc4random_buf(void *, size_t); void arc4random_stir(void); +__uint32_t + arc4random_uniform(__uint32_t); char *getbsize(int *, long *); + /* getcap(3) functions */ char *cgetcap(char *, char *, int); int cgetclose(void); int cgetent(char **, char **, char *); @@ -164,37 +244,36 @@ int daemon(int, int); char *devname(dev_t, mode_t); char *devname_r(dev_t, mode_t, char *, size_t); int getloadavg(double [], int); -const char *getprogname(void); +__const char * + getprogname(void); int heapsort(void *, size_t, size_t, int (*)(const void *, const void *)); -char *initstate(unsigned long, char *, long); +int l64a_r(long, char *, int); int mergesort(void *, size_t, size_t, int (*)(const void *, const void *)); +void qsort_r(void *, size_t, size_t, void *, + int (*)(void *, const void *, const void *)); int radixsort(const unsigned char **, int, const unsigned char *, unsigned int); -int sradixsort(const unsigned char **, int, const unsigned char *, - unsigned int); -int rand_r(unsigned *); -long random(void); void *reallocf(void *, size_t); -char *realpath(const char *, char []); +int rpmatch(const char *); void setprogname(const char *); -char *setstate(char *); -void srandom(unsigned long); +int sradixsort(const unsigned char **, int, const unsigned char *, + unsigned int); +void sranddev(void); void srandomdev(void); +long long + strtonum(const char *, long long, long long, const char **); -#if !defined(__STRICT_ANSI__) && !defined(_KERNEL_VIRTUAL) -__int64_t strtoq(const char *, char **, int); -__uint64_t strtouq(const char *, char **, int); +/* Deprecated interfaces. */ +#if !defined(_KERNEL_VIRTUAL) +__int64_t + strtoq(const char *, char **, int); +__uint64_t + strtouq(const char *, char **, int); #endif -#ifndef __STRICT_ANSI__ -#ifdef __LONG_LONG_SUPPORTED -long long - strtonum(const char *, long long, long long, const char **); -#endif -#endif -void unsetenv(const char *); -#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */ +extern char *suboptarg; /* getsubopt(3) external variable */ +#endif /* __BSD_VISIBLE */ __END_DECLS #endif /* !_STDLIB_H_ */ diff --git a/include/unistd.h b/include/unistd.h index c57a1dcf75..4eb37967be 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -159,7 +159,6 @@ int lwp_create(struct lwp_params *); lwpid_t lwp_gettid(void); char *mkdtemp(char *); int mknod(const char *, mode_t, dev_t); -int mkstemp(char *); int mkstemps(char *, int); char *mktemp(char *); int nfssvc(int, void *); @@ -226,8 +225,6 @@ int varsym_set(int, const char *, const char *); int varsym_get(int, const char *, char *, int); int varsym_list(int, char *, int, int *); -extern char *suboptarg; /* getsubopt(3) external variable */ -int getsubopt(char **, char * const *, char **); #endif /* !_POSIX_SOURCE */ extern int optreset; /* getopt(3) external variable */ __END_DECLS diff --git a/lib/libc/gen/getprogname.c b/lib/libc/gen/getprogname.c index ca70dea85c..619039f184 100644 --- a/lib/libc/gen/getprogname.c +++ b/lib/libc/gen/getprogname.c @@ -1,14 +1,19 @@ /* - * $FreeBSD: src/lib/libc/gen/getprogname.c,v 1.1.2.1 2001/06/14 00:06:12 dd Exp $ + * $FreeBSD: src/lib/libc/gen/getprogname.c,v 1.4 2002/03/29 22:43:41 markm Exp $ * $DragonFly: src/lib/libc/gen/getprogname.c,v 1.3 2005/03/09 18:52:21 joerg Exp $ */ +#include "namespace.h" #include +#include "un-namespace.h" -extern const char *__progname; +#include "libc_private.h" + +__weak_reference(_getprogname, getprogname); const char * -getprogname(void) +_getprogname(void) { + return (__progname); } diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index ec87234961..962ab6bbe6 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -81,4 +81,15 @@ void *__get_errno_GOT_ptr(void); struct statfs; struct statvfs; +/* + * This is a pointer in the C run-time startup code. It is used + * by getprogname() and setprogname(). + */ +extern const char *__progname; + +/* + * Function to clean up streams, called from abort() and exit(). + */ +extern void (*__cleanup)(void); + #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index d8c5cf071e..eb3f737b01 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -1,19 +1,18 @@ # from @(#)Makefile.inc 8.3 (Berkeley) 2/4/95 -# $FreeBSD: src/lib/libc/stdlib/Makefile.inc,v 1.19.2.4 2001/10/02 11:15:38 ru Exp $ +# $FreeBSD: src/lib/libc/stdlib/Makefile.inc,v 1.56 2008/10/17 08:30:20 netchild Exp $ # $DragonFly: src/lib/libc/stdlib/Makefile.inc,v 1.24 2008/10/06 21:01:37 swildner Exp $ # machine-independent stdlib sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/stdlib ${.CURDIR}/../libc/stdlib -MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c bsearch.c calloc.c div.c \ - exit.c getenv.c getopt.c getopt_long.c getsubopt.c hcreate.c heapsort.c \ - imaxabs.c imaxdiv.c \ - labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c merge.c putenv.c \ - qsort.c radixsort.c rand.c \ - random.c reallocf.c realpath.c \ - setenv.c strfmon.c strtod.c strtoimax.c strtol.c \ - strtoll.c strtonum.c strtoq.c strtoul.c strtoull.c strtoumax.c \ - strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c +MISRCS+=a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ + bsearch.c calloc.c div.c exit.c getenv.c getopt.c getopt_long.c \ + getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \ + insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \ + merge.c qsort.c qsort_r.c radixsort.c rand.c random.c \ + reallocf.c realpath.c remque.c strfmon.c strtod.c strtoimax.c \ + strtol.c strtoll.c strtonum.c strtoq.c strtoul.c strtoull.c \ + strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c # machine-dependent stdlib sources .if exists(${.CURDIR}/../libc/${MACHINE_ARCH}/stdlib/Makefile.inc) @@ -21,26 +20,29 @@ MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c bsearch.c calloc.c d .endif .if ${LIB} == "c" -MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ - div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 hcreate.3 \ - imaxabs.3 imaxdiv.3 \ - labs.3 ldiv.3 llabs.3 lldiv.3 lsearch.3 malloc.3 memory.3 \ - qsort.3 radixsort.3 rand.3 random.3 realpath.3 \ - strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 tsearch.3 +MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ + div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \ + hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \ + lsearch.3 malloc.3 memory.3 qsort.3 \ + radixsort.3 rand.3 random.3 \ + realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \ + tsearch.3 +MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.3 MLINKS+=atol.3 atoll.3 MLINKS+=exit.3 _Exit.3 MLINKS+=getenv.3 putenv.3 getenv.3 setenv.3 getenv.3 unsetenv.3 MLINKS+=getopt_long.3 getopt_long_only.3 MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3 +MLINKS+=insque.3 remque.3 MLINKS+=lsearch.3 lfind.3 MLINKS+=malloc.3 calloc.3 malloc.3 free.3 malloc.3 realloc.3 malloc.3 reallocf.3 -MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 +MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 qsort.3 qsort_r.3 MLINKS+=radixsort.3 sradixsort.3 MLINKS+=rand.3 rand_r.3 rand.3 srand.3 rand.3 sranddev.3 MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \ random.3 srandomdev.3 -MLINKS+=strtol.3 strtoll.3 strtol.3 strtoimax.3 strtol.3 strtoq.3 +MLINKS+=strtol.3 strtoimax.3 strtol.3 strtoll.3 strtol.3 strtoq.3 MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtoumax.3 strtoul.3 strtouq.3 MLINKS+=tsearch.3 tdelete.3 tsearch.3 tfind.3 tsearch.3 twalk.3 .endif diff --git a/lib/libc/stdlib/a64l.3 b/lib/libc/stdlib/a64l.3 new file mode 100644 index 0000000000..49c03e715e --- /dev/null +++ b/lib/libc/stdlib/a64l.3 @@ -0,0 +1,187 @@ +.\" Copyright (c) 2005 Tom Rhodes +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD: src/lib/libc/stdlib/a64l.3,v 1.3 2006/09/30 10:29:43 ru Exp $ +.\" +.Dd November 20, 2005 +.Dt A64L 3 +.Os +.Sh NAME +.Nm a64l , +.Nm l64a , +.Nm l64a_r +.Nd "convert between a long integer and a base-64 ASCII string" +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In stdlib.h +.Ft long +.Fn a64l "const char *s" +.Ft char * +.Fn l64a "long int l" +.Ft int +.Fn l64a_r "long int l" "char *buffer" "int buflen" +.Sh DESCRIPTION +These functions are used to maintain numbers stored in radix-64 +.Tn ASCII +characters. +This is a notation by which 32-bit integers can be represented by +up to six characters; each character represents a digit in +radix-64 notation. +If the type long contains more than 32 bits, only the low-order +32 bits are used for these operations. +.Pp +The characters used to represent +.Dq digits +are +.Ql .\& +for 0, +.Ql / +for 1, +.Ql 0 +- +.Ql 9 +for 2 - 11, +.Ql A +- +.Ql Z +for 12 - 37, and +.Ql a +- +.Ql z +for 38 - 63. +.Pp +The +.Fn a64l +function takes a pointer to a radix-64 representation, in which the first +digit is the least significant, and returns a corresponding +.Vt long +value. +If the string pointed to by +.Fa s +contains more than six characters, +.Fn a64l +uses the first six. +If the first six characters of the string contain a null terminator, +.Fn a64l +uses only characters preceding the null terminator. +The +.Fn a64l +function scans the character string from left to right with the least +significant digit on the left, decoding each character as a 6-bit +radix-64 number. +If the type long contains more than 32 bits, the resulting value is +sign-extended. +The behavior of +.Fn a64l +is unspecified if +.Fa s +is a null pointer or the string pointed to by +.Fa s +was not generated by a previous call to +.Fn l64a . +.Pp +The +.Fn l64a +function takes a +.Vt long +argument and returns a pointer to the corresponding +radix-64 representation. +The behavior of +.Fn l64a +is unspecified if value is negative. +.Pp +The value returned by +.Fn l64a +is a pointer into a static buffer. +Subsequent calls to +.Fn l64a +may overwrite the buffer. +.Pp +The +.Fn l64a_r +function performs a conversion identical to that of +.Fn l64a +and stores the resulting representation in the memory area pointed to by +.Fa buffer , +consuming at most +.Fa buflen +characters including the terminating +.Dv NUL +character. +.Sh RETURN VALUES +On successful completion, +.Fn a64l +returns the +.Vt long +value resulting from conversion of the input string. +If a string pointed to by +.Fa s +is an empty string, +.Fn a64l +returns 0. +.Pp +The +.Fn l64a +function returns a pointer to the radix-64 representation. +If value is 0, +.Fn l64a +returns a pointer to an empty string. +.Sh SEE ALSO +.Xr strtoul 3 +.Sh HISTORY +The +.Fn a64l , +.Fn l64a , +and +.Fn l64a_r +functions are derived from +.Nx +with modifications. +They appeared in +.Fx 6.1 . +.Sh AUTHORS +The +.Fn a64l , +.Fn l64a , +and +.Fn l64a_r +functions +were added to +.Fx +by +.An Tom Rhodes Aq trhodes@FreeBSD.org . +Almost all of this manual page came from the +.Tn POSIX +standard. diff --git a/lib/libc/stdlib/a64l.c b/lib/libc/stdlib/a64l.c new file mode 100644 index 0000000000..52b8b17468 --- /dev/null +++ b/lib/libc/stdlib/a64l.c @@ -0,0 +1,34 @@ +/*- + * Written by J.T. Conklin . + * Public domain. + * + * $NetBSD: a64l.c,v 1.8 2000/01/22 22:19:19 mycroft Exp $ + * $FreeBSD: src/lib/libc/stdlib/a64l.c,v 1.2 2006/05/19 19:06:38 jkim Exp $ + */ + +#include +#include + +long +a64l(const char *s) +{ + long shift; + int digit, i, value; + + value = 0; + shift = 0; + for (i = 0; *s != '\0' && i < 6; i++, s++) { + if (*s <= '/') + digit = *s - '/' + 1; + else if (*s <= '0' + 9) + digit = *s - '0' + 2; + else if (*s <= 'A' + 25) + digit = *s - 'A' + 12; + else + digit = *s - 'a' + 38; + + value |= digit << shift; + shift += 6; + } + return (value); +} diff --git a/lib/libc/stdlib/abort.3 b/lib/libc/stdlib/abort.3 index a30a8f3b86..27515777d8 100644 --- a/lib/libc/stdlib/abort.3 +++ b/lib/libc/stdlib/abort.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)abort.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/abort.3,v 1.6.2.2 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/abort.3,v 1.10 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/abort.3,v 1.3 2005/06/02 18:44:07 asmodai Exp $ .\" .Dd June 4, 1993 @@ -62,7 +58,7 @@ Any open streams are flushed and closed. The .Fn abort function is thread-safe. -It is not async-cancel-safe. +It is unknown if it is async-cancel-safe. .Sh RETURN VALUES The .Fn abort @@ -77,3 +73,8 @@ The function conforms to .St -p1003.1-90 . +The +.Fn abort +function also conforms to +.St -isoC-99 +with the implementation specific details as noted above. diff --git a/lib/libc/stdlib/abort.c b/lib/libc/stdlib/abort.c index e315a74884..b8df1fbb8a 100644 --- a/lib/libc/stdlib/abort.c +++ b/lib/libc/stdlib/abort.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -30,23 +26,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/stdlib/abort.c,v 1.5.6.2 2002/10/15 19:46:46 fjoe Exp $ - * $DragonFly: src/lib/libc/stdlib/abort.c,v 1.4 2005/11/20 12:37:48 swildner Exp $ - * * @(#)abort.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/abort.c,v 1.4 2005/11/20 12:37:48 swildner Exp $ */ +#include "namespace.h" #include #include #include #include #include +#include "un-namespace.h" -void (*__cleanup)(); - -extern int __sys_sigprocmask(int, const sigset_t *, sigset_t *); -extern int __sys_sigaction(int, const struct sigaction *, - struct sigaction *); +#include "libc_private.h" void abort(void) @@ -54,31 +47,31 @@ abort(void) struct sigaction act; /* - * POSIX requires we flush stdio buffers on abort + * POSIX requires we flush stdio buffers on abort. + * XXX ISO C requires that abort() be async-signal-safe. */ if (__cleanup) (*__cleanup)(); sigfillset(&act.sa_mask); /* - * don't block SIGABRT to give any handler a chance; we ignore - * any errors -- X311J doesn't allow abort to return anyway. + * Don't block SIGABRT to give any handler a chance; we ignore + * any errors -- ISO C doesn't allow abort to return anyway. */ sigdelset(&act.sa_mask, SIGABRT); - __sys_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); - kill(getpid(), SIGABRT); + _sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); + raise(SIGABRT); /* - * if SIGABRT ignored, or caught and the handler returns, do + * If SIGABRT was ignored, or caught and the handler returns, do * it again, only harder. */ act.sa_handler = SIG_DFL; act.sa_flags = 0; sigfillset(&act.sa_mask); - __sys_sigaction(SIGABRT, &act, NULL); + _sigaction(SIGABRT, &act, NULL); sigdelset(&act.sa_mask, SIGABRT); - __sys_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); - kill(getpid(), SIGABRT); + _sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); + raise(SIGABRT); exit(1); } - diff --git a/lib/libc/stdlib/abs.3 b/lib/libc/stdlib/abs.3 index 707123471f..bec6f104a9 100644 --- a/lib/libc/stdlib/abs.3 +++ b/lib/libc/stdlib/abs.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)abs.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.7.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.13 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/abs.3,v 1.4 2007/12/02 03:29:47 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd November 14, 2001 .Dt ABS 3 .Os .Sh NAME @@ -55,7 +51,7 @@ The function computes the absolute value of the integer -.Ar j . +.Fa j . .Sh IMPLEMENTATION NOTES The .Fn abs @@ -80,6 +76,6 @@ the absolute value. The .Fn abs function conforms to -.St -isoC . +.St -isoC-99 . .Sh BUGS The absolute value of the most negative integer remains negative. diff --git a/lib/libc/stdlib/abs.c b/lib/libc/stdlib/abs.c index 9e0b8f637a..1ae34d412a 100644 --- a/lib/libc/stdlib/abs.c +++ b/lib/libc/stdlib/abs.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,6 +27,7 @@ * SUCH DAMAGE. * * @(#)abs.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/abs.c,v 1.3 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/abs.c,v 1.3 2005/06/02 18:45:06 asmodai Exp $ */ diff --git a/lib/libc/stdlib/alloca.3 b/lib/libc/stdlib/alloca.3 index 2200dd854c..2db52a7da4 100644 --- a/lib/libc/stdlib/alloca.3 +++ b/lib/libc/stdlib/alloca.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,10 +26,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)alloca.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.4.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.13 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/alloca.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" -.Dd June 4, 1993 +.Dd September 5, 2006 .Dt ALLOCA 3 .Os .Sh NAME @@ -58,25 +54,36 @@ return. The .Fn alloca function returns a pointer to the beginning of the allocated space. -If the allocation failed, a -.Dv NULL -pointer is returned. .Sh SEE ALSO .Xr brk 2 , .Xr calloc 3 , .Xr getpagesize 3 , .Xr malloc 3 , .Xr realloc 3 -.Sh BUGS +.Sh HISTORY The .Fn alloca -function -is machine dependent; its use is discouraged. -.\" .Sh HISTORY -.\" The -.\" .Fn alloca -.\" function appeared in +function appeared in +.At 32v . .\" .Bx ?? . .\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd .\" The first man page (or link to a man page that I can find at the .\" moment is 4.3... +.Sh BUGS +The +.Fn alloca +function +is machine and compiler dependent; +its use is discouraged. +.Pp +The +.Fn alloca +function is slightly unsafe because it cannot ensure that the pointer +returned points to a valid and usable block of memory. +The allocation made may exceed the bounds of the stack, or even go +further into other objects in memory, and +.Fn alloca +cannot determine such an error. +Avoid +.Fn alloca +with large unbounded allocations. diff --git a/lib/libc/stdlib/atexit.3 b/lib/libc/stdlib/atexit.3 index 07fcb19d09..80f7bdcedb 100644 --- a/lib/libc/stdlib/atexit.3 +++ b/lib/libc/stdlib/atexit.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)atexit.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.3.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.11 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/atexit.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" -.Dd June 4, 1993 +.Dd September 6, 2002 .Dt ATEXIT 3 .Os .Sh NAME @@ -54,15 +50,27 @@ The .Fn atexit function registers the given -.Ar function +.Fa function to be called at program exit, whether via .Xr exit 3 or via return from the program's -.Em main . +.Fn main . Functions so registered are called in reverse order; no arguments are passed. +.Pp +These functions must not call +.Fn exit ; +if it should be necessary to terminate the process while in such a +function, the +.Xr _exit 2 +function should be used. +(Alternatively, the function may cause abnormal +process termination, for example by calling +.Xr abort 3 . ) +.Pp At least 32 functions can always be registered, and more are allowed as long as sufficient memory can be allocated. +.\" XXX {ATEXIT_MAX} is not implemented yet .Sh RETURN VALUES .Rv -std atexit .Sh ERRORS diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c index ace624547e..03f8c2bc09 100644 --- a/lib/libc/stdlib/atexit.c +++ b/lib/libc/stdlib/atexit.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -33,28 +29,29 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.3.6.1 2002/03/10 20:28:40 tegge Exp $ - * $DragonFly: src/lib/libc/stdlib/atexit.c,v 1.7 2006/08/03 16:40:46 swildner Exp $ - * * @(#)atexit.c 8.2 (Berkeley) 7/3/94 + * $FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/atexit.c,v 1.7 2006/08/03 16:40:46 swildner Exp $ */ +#include "namespace.h" #include #include #include +#include #include "atexit.h" +#include "un-namespace.h" #include "libc_private.h" -#include "spinlock.h" -#define ATEXIT_FN_EMPTY 0 -#define ATEXIT_FN_STD 1 -#define ATEXIT_FN_CXA 2 +#define ATEXIT_FN_EMPTY 0 +#define ATEXIT_FN_STD 1 +#define ATEXIT_FN_CXA 2 -static spinlock_t thread_lock = _SPINLOCK_INITIALIZER; +static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER; -#define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&thread_lock); -#define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&thread_lock); +#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x) +#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x) struct atexit { struct atexit *next; /* next in list */ @@ -83,21 +80,21 @@ atexit_register(struct atexit_fn *fptr) static struct atexit __atexit0; /* one guaranteed table */ struct atexit *p; - THREAD_LOCK(); + _MUTEX_LOCK(&atexit_mutex); if ((p = __atexit) == NULL) __atexit = p = &__atexit0; else while (p->ind >= ATEXIT_SIZE) { struct atexit *old__atexit; old__atexit = __atexit; - THREAD_UNLOCK(); + _MUTEX_UNLOCK(&atexit_mutex); if ((p = (struct atexit *)malloc(sizeof(*p))) == NULL) return (-1); - THREAD_LOCK(); + _MUTEX_LOCK(&atexit_mutex); if (old__atexit != __atexit) { /* Lost race, retry operation */ - THREAD_UNLOCK(); + _MUTEX_UNLOCK(&atexit_mutex); free(p); - THREAD_LOCK(); + _MUTEX_LOCK(&atexit_mutex); p = __atexit; continue; } @@ -106,7 +103,7 @@ atexit_register(struct atexit_fn *fptr) __atexit = p; } p->fns[p->ind++] = *fptr; - THREAD_UNLOCK(); + _MUTEX_UNLOCK(&atexit_mutex); return (0); } @@ -124,7 +121,7 @@ atexit(void (*func)(void)) fn.fn_arg = NULL; fn.fn_dso = NULL; - error = atexit_register(&fn); + error = atexit_register(&fn); return (error); } @@ -143,7 +140,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso) fn.fn_arg = arg; fn.fn_dso = dso; - error = atexit_register(&fn); + error = atexit_register(&fn); return (error); } @@ -159,7 +156,7 @@ __cxa_finalize(void *dso) struct atexit_fn fn; int n; - THREAD_LOCK(); + _MUTEX_LOCK(&atexit_mutex); for (p = __atexit; p; p = p->next) { for (n = p->ind; --n >= 0;) { if (p->fns[n].fn_type == ATEXIT_FN_EMPTY) @@ -172,15 +169,15 @@ __cxa_finalize(void *dso) has already been called. */ p->fns[n].fn_type = ATEXIT_FN_EMPTY; - THREAD_UNLOCK(); - + _MUTEX_UNLOCK(&atexit_mutex); + /* Call the function of correct type. */ if (fn.fn_type == ATEXIT_FN_CXA) fn.fn_ptr.cxa_func(fn.fn_arg); else if (fn.fn_type == ATEXIT_FN_STD) fn.fn_ptr.std_func(); - THREAD_LOCK(); + _MUTEX_LOCK(&atexit_mutex); } } - THREAD_UNLOCK(); + _MUTEX_UNLOCK(&atexit_mutex); } diff --git a/lib/libc/stdlib/atexit.h b/lib/libc/stdlib/atexit.h index bb424f7b77..f55b1f6603 100644 --- a/lib/libc/stdlib/atexit.h +++ b/lib/libc/stdlib/atexit.h @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,10 +27,11 @@ * SUCH DAMAGE. * * @(#)atexit.h 8.2 (Berkeley) 7/3/94 + * $FreeBSD: src/lib/libc/stdlib/atexit.h,v 1.4 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/atexit.h,v 1.3 2004/01/24 22:18:12 joerg Exp $ */ /* must be at least 32 to guarantee ANSI conformance */ #define ATEXIT_SIZE 32 -void __cxa_finalize(void *dso); +void __cxa_finalize(void *); diff --git a/lib/libc/stdlib/atof.3 b/lib/libc/stdlib/atof.3 index 1ceb89efa4..6d8a03a2d4 100644 --- a/lib/libc/stdlib/atof.3 +++ b/lib/libc/stdlib/atof.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)atof.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.4.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.17 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/atof.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd June 4, 1993 @@ -55,15 +51,35 @@ string to double The .Fn atof function converts the initial portion of the string pointed to by -.Ar nptr +.Fa nptr to -.Ar double +.Vt double representation. .Pp It is equivalent to: .Bd -literal -offset indent strtod(nptr, (char **)NULL); .Ed +.Pp +The decimal point +character is defined in the program's locale (category +.Dv LC_NUMERIC ) . +.Sh IMPLEMENTATION NOTES +The +.Fn atof +function is not thread-safe and also not async-cancel-safe. +.Pp +The +.Fn atof +function has been deprecated by +.Fn strtod +and should not be used in new code. +.Sh ERRORS +The function +.Fn atof +need not affect the value of +.Va errno +on an error. .Sh SEE ALSO .Xr atoi 3 , .Xr atol 3 , @@ -74,4 +90,7 @@ strtod(nptr, (char **)NULL); The .Fn atof function conforms to -.St -isoC . +.St -p1003.1-90 , +.St -isoC , +and +.St -isoC-99 . diff --git a/lib/libc/stdlib/atof.c b/lib/libc/stdlib/atof.c index 1d1e914793..30ec8cf925 100644 --- a/lib/libc/stdlib/atof.c +++ b/lib/libc/stdlib/atof.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,14 +27,14 @@ * SUCH DAMAGE. * * @(#)atof.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/atof.c,v 1.6 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/atof.c,v 1.3 2005/11/20 12:37:48 swildner Exp $ */ #include -#include double atof(const char *ascii) { - return (strtod(ascii, NULL)); + return(strtod(ascii, (char **)NULL)); } diff --git a/lib/libc/stdlib/atoi.3 b/lib/libc/stdlib/atoi.3 index 7617239698..3f58a43848 100644 --- a/lib/libc/stdlib/atoi.3 +++ b/lib/libc/stdlib/atoi.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)atoi.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.3.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.14 2007/10/19 06:23:39 davidxu Exp $ .\" $DragonFly: src/lib/libc/stdlib/atoi.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd June 4, 1993 @@ -55,15 +51,27 @@ string to integer The .Fn atoi function converts the initial portion of the string pointed to by -.Em nptr +.Fa nptr to -.Em integer +.Vt int representation. .Pp It is equivalent to: .Bd -literal -offset indent (int)strtol(nptr, (char **)NULL, 10); .Ed +.Pp +The +.Fn atoi +function has been deprecated by +.Fn strtol +and should not be used in new code. +.Sh ERRORS +The function +.Fn atoi +need not affect the value of +.Va errno +on an error. .Sh SEE ALSO .Xr atof 3 , .Xr atol 3 , @@ -74,4 +82,7 @@ It is equivalent to: The .Fn atoi function conforms to -.St -isoC . +.St -p1003.1-90 , +.St -isoC , +and +.St -isoC-99 . diff --git a/lib/libc/stdlib/atoi.c b/lib/libc/stdlib/atoi.c index 9c92db5c15..ed243c3fb1 100644 --- a/lib/libc/stdlib/atoi.c +++ b/lib/libc/stdlib/atoi.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,11 +27,11 @@ * SUCH DAMAGE. * * @(#)atoi.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.6 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/atoi.c,v 1.3 2005/11/20 12:37:48 swildner Exp $ */ #include -#include int atoi(const char *str) diff --git a/lib/libc/stdlib/atol.3 b/lib/libc/stdlib/atol.3 index cb95bf3475..76c1f29e2c 100644 --- a/lib/libc/stdlib/atol.3 +++ b/lib/libc/stdlib/atol.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,14 +30,15 @@ .\" SUCH DAMAGE. .\" .\" @(#)atol.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.13 2002/01/09 14:03:54 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.14 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/atol.3,v 1.3 2005/11/01 18:16:52 swildner Exp $ .\" .Dd November 28, 2001 .Dt ATOL 3 .Os .Sh NAME -.Nm atol , atoll +.Nm atol , +.Nm atoll .Nd convert .Tn ASCII string to diff --git a/lib/libc/stdlib/atol.c b/lib/libc/stdlib/atol.c index dbc227d576..b0ca8132ca 100644 --- a/lib/libc/stdlib/atol.c +++ b/lib/libc/stdlib/atol.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,10 +27,10 @@ * SUCH DAMAGE. * * @(#)atol.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/atol.c,v 1.5 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/atol.c,v 1.3 2005/11/20 12:37:48 swildner Exp $ */ -#include #include long diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3 index 6306b7510e..abe85e17c2 100644 --- a/lib/libc/stdlib/bsearch.3 +++ b/lib/libc/stdlib/bsearch.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94 -.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.4.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.9 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/bsearch.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd April 19, 1994 diff --git a/lib/libc/stdlib/bsearch.c b/lib/libc/stdlib/bsearch.c index 44dd92ed3b..5ee5d37b5b 100644 --- a/lib/libc/stdlib/bsearch.c +++ b/lib/libc/stdlib/bsearch.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,6 +27,7 @@ * SUCH DAMAGE. * * @(#)bsearch.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.4 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/bsearch.c,v 1.5 2005/11/20 12:37:48 swildner Exp $ */ @@ -66,7 +63,7 @@ bsearch(const void *key, const void *base0, size_t nmemb, size_t size, p = base + (lim >> 1) * size; cmp = (*compar)(key, p); if (cmp == 0) - return ((void *)p); + return (__DECONST(void *, p)); if (cmp > 0) { /* key > p: move right */ base = (char *)p + size; lim--; diff --git a/lib/libc/stdlib/div.3 b/lib/libc/stdlib/div.3 index a937f5ed56..d30675960a 100644 --- a/lib/libc/stdlib/div.3 +++ b/lib/libc/stdlib/div.3 @@ -11,10 +11,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -32,10 +28,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)div.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.3.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.9 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/div.3,v 1.3 2008/01/25 23:24:31 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd November 14, 2001 .Dt DIV 3 .Os .Sh NAME @@ -56,11 +52,11 @@ computes the value and returns the quotient and remainder in a structure named .Fa div_t that contains two -.Em int +.Vt int members named -.Fa quot +.Va quot and -.Fa rem . +.Va rem . .Sh SEE ALSO .Xr imaxdiv 3 , .Xr ldiv 3 , @@ -70,4 +66,4 @@ The .Fn div function conforms to -.St -isoC . +.St -isoC-99 . diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c index d3066d2daf..dc7759a794 100644 --- a/lib/libc/stdlib/div.c +++ b/lib/libc/stdlib/div.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -34,6 +30,7 @@ * SUCH DAMAGE. * * @(#)div.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/div.c,v 1.3 2007/01/09 00:28:09 imp Exp $ * $DragonFly: src/lib/libc/stdlib/div.c,v 1.3 2005/11/20 12:37:48 swildner Exp $ */ diff --git a/lib/libc/stdlib/exit.3 b/lib/libc/stdlib/exit.3 index 2d499742de..12f9aac70e 100644 --- a/lib/libc/stdlib/exit.3 +++ b/lib/libc/stdlib/exit.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)exit.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/exit.3,v 1.6.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/exit.3,v 1.16 2007/01/09 00:28:09 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/exit.3,v 1.3 2007/06/15 19:36:33 swildner Exp $ .\" .Dd June 15, 2007 @@ -77,36 +73,52 @@ Unlink all files created with the function. .El .Pp -The C99 function +The .Fn _Exit -terminates without calling the functions registered with +function terminates without calling the functions registered with the .Xr atexit 3 -by just calling -.Xr _exit 2 . -Code intended to be portable should always use -.Xr _exit 2 -directly as it is defined by -.St -susv2 -as well. +function, and may or may not perform the other actions listed. +Both functions make the low-order eight bits of the +.Fa status +argument available to a parent process which has called a +.Xr wait 2 Ns -family +function. .Pp -Passing arbitrary values back to the environment as -.Ar status -is considered bad style; -you should use the values -.Dv EXIT_SUCCESS +The C Standard +.Pq St -isoC-99 +defines the values +.Li 0 , +.Dv EXIT_SUCCESS , and -.Dv EXIT_FAILURE . -If portability is not a concern, you may -use the values described in -.Xr sysexits 3 . +.Dv EXIT_FAILURE +as possible values of +.Fa status . +Cooperating processes may use other values; +in a program which might be called by a mail transfer agent, the +values described in +.Xr sysexits 3 +may be used to provide more information to the parent process. +.Pp +Note that +.Fn exit +does nothing to prevent bottomless recursion should a function registered +using +.Xr atexit 3 +itself call +.Fn exit . +Such functions must call +.Fn _Exit +instead (although this has other effects as well which may not be desired). .Sh RETURN VALUES The .Fn exit and .Fn _Exit -functions never return. +functions +never return. .Sh SEE ALSO .Xr _exit 2 , +.Xr wait 2 , .Xr atexit 3 , .Xr intro 3 , .Xr sysexits 3 , diff --git a/lib/libc/stdlib/exit.c b/lib/libc/stdlib/exit.c index 6f2e929298..ee33ea5841 100644 --- a/lib/libc/stdlib/exit.c +++ b/lib/libc/stdlib/exit.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -30,19 +26,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/stdlib/exit.c,v 1.3.6.1 2001/03/05 11:33:57 obrien Exp $ - * $DragonFly: src/lib/libc/stdlib/exit.c,v 1.8 2005/11/20 12:37:48 swildner Exp $ - * * @(#)exit.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/exit.c,v 1.9 2007/01/09 00:28:09 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/exit.c,v 1.8 2005/11/20 12:37:48 swildner Exp $ */ #include "namespace.h" #include #include #include "un-namespace.h" + #include "atexit.h" +#include "libc_private.h" -void (*__cleanup)(); +void (*__cleanup)(void); /* * This variable is zero until a process has created a thread. @@ -60,12 +57,11 @@ void exit(int status) { /* Ensure that the auto-initialization routine is linked in: */ - extern int _thread_autoinit_dummy_decl; + extern int _thread_autoinit_dummy_decl; _thread_autoinit_dummy_decl = 1; __cxa_finalize(NULL); - if (__cleanup) (*__cleanup)(); _exit(status); diff --git a/lib/libc/stdlib/getenv.3 b/lib/libc/stdlib/getenv.3 index 57b4495b92..34a89c6c5c 100644 --- a/lib/libc/stdlib/getenv.3 +++ b/lib/libc/stdlib/getenv.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)getenv.3 8.2 (Berkeley) 12/11/93 -.\" $FreeBSD: src/lib/libc/stdlib/getenv.3,v 1.4.2.7 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/getenv.3,v 1.27 2007/07/04 00:00:39 scf Exp $ .\" $DragonFly: src/lib/libc/stdlib/getenv.3,v 1.5 2006/02/17 19:35:06 swildner Exp $ .\" -.Dd December 11, 1993 +.Dd June 20, 2007 .Dt GETENV 3 .Os .Sh NAME @@ -55,58 +51,56 @@ .Ft int .Fn setenv "const char *name" "const char *value" "int overwrite" .Ft int -.Fn putenv "const char *string" -.Ft void +.Fn putenv "char *string" +.Ft int .Fn unsetenv "const char *name" .Sh DESCRIPTION These functions set, unset and fetch environment variables from the host .Em environment list . -For compatibility with differing environment conventions, -the given arguments -.Ar name -and -.Ar value -may be appended and prepended, -respectively, -with an equal sign -.Dq Li \&= . .Pp The .Fn getenv function obtains the current value of the environment variable, -.Ar name . -If the variable -.Ar name -is not in the current environment, -a null pointer is returned. +.Fa name . +The application should not modify the string pointed +to by the +.Fn getenv +function. .Pp The .Fn setenv function inserts or resets the environment variable -.Ar name +.Fa name in the current environment list. If the variable -.Ar name +.Fa name does not exist in the list, it is inserted with the given -.Ar value . +.Fa value . If the variable does exist, the argument -.Ar overwrite +.Fa overwrite is tested; if -.Ar overwrite is -zero, the +.Fa overwrite +is zero, the variable is not reset, otherwise it is reset to the given -.Ar value . +.Fa value . .Pp The .Fn putenv -function takes an argument of the form ``name=value'' and is -equivalent to: -.Bd -literal -offset indent -setenv(name, value, 1); -.Ed +function takes an argument of the form ``name=value'' and +puts it directly into the current environment, +so altering the argument shall change the environment. +If the variable +.Fa name +does not exist in the list, +it is inserted with the given +.Fa value . +If the variable +.Fa name +does exist, it is reset to the given +.Fa value . .Pp The .Fn unsetenv @@ -115,22 +109,66 @@ deletes all instances of the variable name pointed to by .Fa name from the list. .Sh RETURN VALUES -.Rv -std setenv putenv -.Pp The .Fn getenv -function returns NULL if the environment variable was not found. -If the variable was found, -it returns the value of the variable as a NULL terminated string. -This string should not be modified or freed. +function returns the value of the environment variable as a +.Dv NUL Ns +-terminated string. +If the variable +.Fa name +is not in the current environment, +.Dv NULL +is returned. +.Pp +.Rv -std setenv putenv unsetenv .Sh ERRORS .Bl -tag -width Er -.It Bq Er ENOMEM +.It Bq Er EINVAL The function +.Fn getenv , .Fn setenv or +.Fn unsetenv +failed because the +.Fa name +is a +.Dv NULL +pointer, points to an empty string, or points to a string containing an +.Dq Li \&= +character. +.Pp +The function +.Fn putenv +failed because +.Fa string +is a +.Dv NULL +pointer, +.Fa string is without an +.Dq Li \&= +character or +.Dq Li \&= +is the first character in +.Fa string . +This does not follow the +.Tn POSIX +specification. +.It Bq Er ENOMEM +The function +.Fn setenv , +.Fn unsetenv +or .Fn putenv failed because they were unable to allocate memory for the environment. +.It Bq Er EFAULT +The functions +.Fn setenv , +.Fn unsetenv +or +.Fn putenv +failed to make a valid copy of the environment due to the environment being +corrupt (i.e., a name without a value). A warning will be output to stderr with +information about the issue. .El .Sh SEE ALSO .Xr csh 1 , @@ -142,6 +180,13 @@ The .Fn getenv function conforms to .St -isoC . +The +.Fn setenv , +.Fn putenv +and +.Fn unsetenv +functions conforms to +.St -p1003.1-2001 . .Sh HISTORY The functions .Fn setenv @@ -153,20 +198,33 @@ The .Fn putenv function appeared in .Bx 4.3 Reno . +.Pp +Until +.Fx 7.0 , +.Fn putenv +would make a copy of +.Fa string +and insert it into the environment using +.Fn setenv . +This was changed to use +.Fa string +as the memory location of the ``name=value'' pair to follow the +.Tn POSIX +specification. .Sh BUGS Successive calls to .Fn setenv -or -.Fn putenv -assigning a differently sized -.Ar value -to the same -.Ar name -will result in a memory leak. The +that assign a larger-sized +.Fa value +than any previous value to the same +.Fa name +will result in a memory leak. +The .Dx -semantics for these functions +semantics for this function (namely, that the contents of -.Ar value +.Fa value are copied and that old values remain accessible indefinitely) make this -bug unavoidable. Future versions may eliminate one or both of these +bug unavoidable. +Future versions may eliminate one or both of these semantic guarantees in order to fix the bug. diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c dissimilarity index 71% index aa552dac4f..731b3c50e4 100644 --- a/lib/libc/stdlib/getenv.c +++ b/lib/libc/stdlib/getenv.c @@ -1,88 +1,684 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)getenv.c 8.1 (Berkeley) 6/4/93 - * $DragonFly: src/lib/libc/stdlib/getenv.c,v 1.5 2005/04/28 13:51:55 joerg Exp $ - */ - -#include -#include -#include - -char *__findenv(const char *, size_t *); - -extern char **environ; - -/* - * __findenv -- - * Returns pointer to value associated with name, if any, else NULL. - * Sets offset to be the offset of the name/value combination in the - * environmental array, for use by setenv(3) and unsetenv(3). - * Explicitly removes '=' in argument name. - * - * This routine *should* be a static; don't use it. - */ -char * -__findenv(const char *name, size_t *offset) -{ - size_t len, i; - const char *np; - char **p, *cp; - - if (name == NULL || environ == NULL) - return (NULL); - for (np = name; *np && *np != '='; ++np) - continue; - len = np - name; - for (p = environ; (cp = *p) != NULL; ++p) { - for (np = name, i = len; i && *cp; i--) - if (*cp++ != *np++) - break; - if (i == 0 && *cp++ == '=') { - *offset = p - environ; - return (cp); - } - } - return (NULL); -} - -/* - * getenv -- - * Returns ptr to value associated with name, if any, else NULL. - */ -char * -getenv(const char *name) -{ - size_t offset; - - return (__findenv(name, &offset)); -} +/*- + * Copyright (c) 2007-2008 Sean C. Farley + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/stdlib/getenv.c,v 1.15 2008/08/03 22:47:23 scf Exp $ + * $DragonFly: src/lib/libc/stdlib/getenv.c,v 1.5 2005/04/28 13:51:55 joerg Exp $ + */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" + + +static const char CorruptEnvFindMsg[] = "environment corrupt; unable to find "; +static const char CorruptEnvValueMsg[] = + "environment corrupt; missing value for "; + + +/* + * Standard environ. environ variable is exposed to entire process. + * + * origEnviron: Upon cleanup on unloading of library or failure, this + * allows environ to return to as it was before. + * environSize: Number of variables environ can hold. Can only + * increase. + * intEnviron: Internally-built environ. Exposed via environ during + * (re)builds of the environment. + */ +extern char **environ; +static char **origEnviron; +static char **intEnviron = NULL; +static int environSize = 0; + +/* + * Array of environment variables built from environ. Each element records: + * name: Pointer to name=value string + * name length: Length of name not counting '=' character + * value: Pointer to value within same string as name + * value size: Size (not length) of space for value not counting the + * nul character + * active state: true/false value to signify whether variable is active. + * Useful since multiple variables with the same name can + * co-exist. At most, one variable can be active at any + * one time. + * putenv: Created from putenv() call. This memory must not be + * reused. + */ +static struct envVars { + size_t nameLen; + size_t valueSize; + char *name; + char *value; + bool active; + bool putenv; +} *envVars = NULL; + +/* + * Environment array information. + * + * envActive: Number of active variables in array. + * envVarsSize: Size of array. + * envVarsTotal: Number of total variables in array (active or not). + */ +static int envActive = 0; +static int envVarsSize = 0; +static int envVarsTotal = 0; + + +/* Deinitialization of new environment. */ +static void __attribute__ ((destructor)) __clean_env_destructor(void); + + +/* + * A simple version of warnx() to avoid the bloat of including stdio in static + * binaries. + */ +static void +__env_warnx(const char *msg, const char *name, size_t nameLen) +{ + static const char nl[] = "\n"; + static const char progSep[] = ": "; + + _write(STDERR_FILENO, _getprogname(), strlen(_getprogname())); + _write(STDERR_FILENO, progSep, sizeof(progSep) - 1); + _write(STDERR_FILENO, msg, strlen(msg)); + _write(STDERR_FILENO, name, nameLen); + _write(STDERR_FILENO, nl, sizeof(nl) - 1); + + return; +} + + +/* + * Inline strlen() for performance. Also, perform check for an equals sign. + * Cheaper here than peforming a strchr() later. + */ +static inline size_t +__strleneq(const char *str) +{ + const char *s; + + for (s = str; *s != '\0'; ++s) + if (*s == '=') + return (0); + + return (s - str); +} + + +/* + * Comparison of an environment name=value to a name. + */ +static inline bool +strncmpeq(const char *nameValue, const char *name, size_t nameLen) +{ + if (strncmp(nameValue, name, nameLen) == 0 && nameValue[nameLen] == '=') + return (true); + + return (false); +} + + +/* + * Using environment, returns pointer to value associated with name, if any, + * else NULL. If the onlyActive flag is set to true, only variables that are + * active are returned else all are. + */ +static inline char * +__findenv(const char *name, size_t nameLen, int *envNdx, bool onlyActive) +{ + int ndx; + + /* + * Find environment variable from end of array (more likely to be + * active). A variable created by putenv is always active or it is not + * tracked in the array. + */ + for (ndx = *envNdx; ndx >= 0; ndx--) + if (envVars[ndx].putenv) { + if (strncmpeq(envVars[ndx].name, name, nameLen)) { + *envNdx = ndx; + return (envVars[ndx].name + nameLen + + sizeof ("=") - 1); + } + } else if ((!onlyActive || envVars[ndx].active) && + (envVars[ndx].nameLen == nameLen && + strncmpeq(envVars[ndx].name, name, nameLen))) { + *envNdx = ndx; + return (envVars[ndx].value); + } + + return (NULL); +} + + +/* + * Using environ, returns pointer to value associated with name, if any, else + * NULL. Used on the original environ passed into the program. + */ +static char * +__findenv_environ(const char *name, size_t nameLen) +{ + int envNdx; + + /* Find variable within environ. */ + for (envNdx = 0; environ[envNdx] != NULL; envNdx++) + if (strncmpeq(environ[envNdx], name, nameLen)) + return (&(environ[envNdx][nameLen + sizeof("=") - 1])); + + return (NULL); +} + + +/* + * Remove variable added by putenv() from variable tracking array. + */ +static void +__remove_putenv(int envNdx) +{ + envVarsTotal--; + if (envVarsTotal > envNdx) + memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]), + (envVarsTotal - envNdx) * sizeof (*envVars)); + memset(&(envVars[envVarsTotal]), 0, sizeof (*envVars)); + + return; +} + + +/* + * Deallocate the environment built from environ as well as environ then set + * both to NULL. Eases debugging of memory leaks. + */ +static void +__clean_env(bool freeVars) +{ + int envNdx; + + /* Deallocate environment and environ if created by *env(). */ + if (envVars != NULL) { + for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) + /* Free variables or deactivate them. */ + if (envVars[envNdx].putenv) { + if (!freeVars) + __remove_putenv(envNdx); + } else { + if (freeVars) + free(envVars[envNdx].name); + else + envVars[envNdx].active = false; + } + if (freeVars) { + free(envVars); + envVars = NULL; + } else + envActive = 0; + + /* Restore original environ if it has not updated by program. */ + if (origEnviron != NULL) { + if (environ == intEnviron) + environ = origEnviron; + free(intEnviron); + intEnviron = NULL; + environSize = 0; + } + } + + return; +} + + +/* + * Using the environment, rebuild the environ array for use by other C library + * calls that depend upon it. + */ +static int +__rebuild_environ(int newEnvironSize) +{ + char **tmpEnviron; + int envNdx; + int environNdx; + int tmpEnvironSize; + + /* Resize environ. */ + if (newEnvironSize > environSize) { + tmpEnvironSize = newEnvironSize * 2; + tmpEnviron = realloc(intEnviron, sizeof (*intEnviron) * + (tmpEnvironSize + 1)); + if (tmpEnviron == NULL) + return (-1); + environSize = tmpEnvironSize; + intEnviron = tmpEnviron; + } + envActive = newEnvironSize; + + /* Assign active variables to environ. */ + for (envNdx = envVarsTotal - 1, environNdx = 0; envNdx >= 0; envNdx--) + if (envVars[envNdx].active) + intEnviron[environNdx++] = envVars[envNdx].name; + intEnviron[environNdx] = NULL; + + /* Always set environ which may have been replaced by program. */ + environ = intEnviron; + + return (0); +} + + +/* + * Enlarge new environment. + */ +static inline bool +__enlarge_env(void) +{ + int newEnvVarsSize; + struct envVars *tmpEnvVars; + + envVarsTotal++; + if (envVarsTotal > envVarsSize) { + newEnvVarsSize = envVarsTotal * 2; + tmpEnvVars = realloc(envVars, sizeof (*envVars) * + newEnvVarsSize); + if (tmpEnvVars == NULL) { + envVarsTotal--; + return (false); + } + envVarsSize = newEnvVarsSize; + envVars = tmpEnvVars; + } + + return (true); +} + + +/* + * Using environ, build an environment for use by standard C library calls. + */ +static int +__build_env(void) +{ + char **env; + int activeNdx; + int envNdx; + int savedErrno; + size_t nameLen; + + /* Check for non-existant environment. */ + if (environ == NULL || environ[0] == NULL) + return (0); + + /* Count environment variables. */ + for (env = environ, envVarsTotal = 0; *env != NULL; env++) + envVarsTotal++; + envVarsSize = envVarsTotal * 2; + + /* Create new environment. */ + envVars = calloc(1, sizeof (*envVars) * envVarsSize); + if (envVars == NULL) + goto Failure; + + /* Copy environ values and keep track of them. */ + for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) { + envVars[envNdx].putenv = false; + envVars[envNdx].name = + strdup(environ[envVarsTotal - envNdx - 1]); + if (envVars[envNdx].name == NULL) + goto Failure; + envVars[envNdx].value = strchr(envVars[envNdx].name, '='); + if (envVars[envNdx].value != NULL) { + envVars[envNdx].value++; + envVars[envNdx].valueSize = + strlen(envVars[envNdx].value); + } else { + __env_warnx(CorruptEnvValueMsg, envVars[envNdx].name, + strlen(envVars[envNdx].name)); + errno = EFAULT; + goto Failure; + } + + /* + * Find most current version of variable to make active. This + * will prevent multiple active variables from being created + * during this initialization phase. + */ + nameLen = envVars[envNdx].value - envVars[envNdx].name - 1; + envVars[envNdx].nameLen = nameLen; + activeNdx = envVarsTotal - 1; + if (__findenv(envVars[envNdx].name, nameLen, &activeNdx, + false) == NULL) { + __env_warnx(CorruptEnvFindMsg, envVars[envNdx].name, + nameLen); + errno = EFAULT; + goto Failure; + } + envVars[activeNdx].active = true; + } + + /* Create a new environ. */ + origEnviron = environ; + environ = NULL; + if (__rebuild_environ(envVarsTotal) == 0) + return (0); + +Failure: + savedErrno = errno; + __clean_env(true); + errno = savedErrno; + + return (-1); +} + + +/* + * Destructor function with default argument to __clean_env(). + */ +static void +__clean_env_destructor(void) +{ + __clean_env(true); + + return; +} + + +/* + * Returns the value of a variable or NULL if none are found. + */ +char * +getenv(const char *name) +{ + int envNdx; + size_t nameLen; + + /* Check for malformed name. */ + if (name == NULL || (nameLen = __strleneq(name)) == 0) { + errno = EINVAL; + return (NULL); + } + + /* + * An empty environment (environ or its first value) regardless if + * environ has been copied before will return a NULL. + * + * If the environment is not empty, find an environment variable via + * environ if environ has not been copied via an *env() call or been + * replaced by a running program, otherwise, use the rebuilt + * environment. + */ + if (environ == NULL || environ[0] == NULL) + return (NULL); + else if (envVars == NULL || environ != intEnviron) + return (__findenv_environ(name, nameLen)); + else { + envNdx = envVarsTotal - 1; + return (__findenv(name, nameLen, &envNdx, true)); + } +} + + +/* + * Set the value of a variable. Older settings are labeled as inactive. If an + * older setting has enough room to store the new value, it will be reused. No + * previous variables are ever freed here to avoid causing a segmentation fault + * in a user's code. + * + * The variables nameLen and valueLen are passed into here to allow the caller + * to calculate the length by means besides just strlen(). + */ +static int +__setenv(const char *name, size_t nameLen, const char *value, int overwrite) +{ + bool reuse; + char *env; + int envNdx; + int newEnvActive; + size_t valueLen; + + /* Find existing environment variable large enough to use. */ + envNdx = envVarsTotal - 1; + newEnvActive = envActive; + valueLen = strlen(value); + reuse = false; + if (__findenv(name, nameLen, &envNdx, false) != NULL) { + /* Deactivate entry if overwrite is allowed. */ + if (envVars[envNdx].active) { + if (overwrite == 0) + return (0); + envVars[envNdx].active = false; + newEnvActive--; + } + + /* putenv() created variable cannot be reused. */ + if (envVars[envNdx].putenv) + __remove_putenv(envNdx); + + /* Entry is large enough to reuse. */ + else if (envVars[envNdx].valueSize >= valueLen) + reuse = true; + } + + /* Create new variable if none was found of sufficient size. */ + if (! reuse) { + /* Enlarge environment. */ + envNdx = envVarsTotal; + if (!__enlarge_env()) + return (-1); + + /* Create environment entry. */ + envVars[envNdx].name = malloc(nameLen + sizeof ("=") + + valueLen); + if (envVars[envNdx].name == NULL) { + envVarsTotal--; + return (-1); + } + envVars[envNdx].nameLen = nameLen; + envVars[envNdx].valueSize = valueLen; + + /* Save name of name/value pair. */ + env = stpcpy(envVars[envNdx].name, name); + if ((envVars[envNdx].name)[nameLen] != '=') + env = stpcpy(env, "="); + } + else + env = envVars[envNdx].value; + + /* Save value of name/value pair. */ + strcpy(env, value); + envVars[envNdx].value = env; + envVars[envNdx].active = true; + newEnvActive++; + + /* No need to rebuild environ if an active variable was reused. */ + if (reuse && newEnvActive == envActive) + return (0); + else + return (__rebuild_environ(newEnvActive)); +} + + +/* + * If the program attempts to replace the array of environment variables + * (environ) environ or sets the first varible to NULL, then deactivate all + * variables and merge in the new list from environ. + */ +static int +__merge_environ(void) +{ + char **env; + char *equals; + + /* + * Internally-built environ has been replaced or cleared (detected by + * using the count of active variables against a NULL as the first value + * in environ). Clean up everything. + */ + if (intEnviron != NULL && (environ != intEnviron || (envActive > 0 && + environ[0] == NULL))) { + /* Deactivate all environment variables. */ + if (envActive > 0) { + origEnviron = NULL; + __clean_env(false); + } + + /* + * Insert new environ into existing, yet deactivated, + * environment array. + */ + origEnviron = environ; + if (origEnviron != NULL) + for (env = origEnviron; *env != NULL; env++) { + if ((equals = strchr(*env, '=')) == NULL) { + __env_warnx(CorruptEnvValueMsg, *env, + strlen(*env)); + errno = EFAULT; + return (-1); + } + if (__setenv(*env, equals - *env, equals + 1, + 1) == -1) + return (-1); + } + } + + return (0); +} + + +/* + * The exposed setenv() that peforms a few tests before calling the function + * (__setenv()) that does the actual work of inserting a variable into the + * environment. + */ +int +setenv(const char *name, const char *value, int overwrite) +{ + size_t nameLen; + + /* Check for malformed name. */ + if (name == NULL || (nameLen = __strleneq(name)) == 0) { + errno = EINVAL; + return (-1); + } + + /* Initialize environment. */ + if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) + return (-1); + + return (__setenv(name, nameLen, value, overwrite)); +} + + +/* + * Insert a "name=value" string into the environment. Special settings must be + * made to keep setenv() from reusing this memory block and unsetenv() from + * allowing it to be tracked. + */ +int +putenv(char *string) +{ + char *equals; + int envNdx; + int newEnvActive; + size_t nameLen; + + /* Check for malformed argument. */ + if (string == NULL || (equals = strchr(string, '=')) == NULL || + (nameLen = equals - string) == 0) { + errno = EINVAL; + return (-1); + } + + /* Initialize environment. */ + if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) + return (-1); + + /* Deactivate previous environment variable. */ + envNdx = envVarsTotal - 1; + newEnvActive = envActive; + if (__findenv(string, nameLen, &envNdx, true) != NULL) { + /* Reuse previous putenv slot. */ + if (envVars[envNdx].putenv) { + envVars[envNdx].name = string; + return (__rebuild_environ(envActive)); + } else { + newEnvActive--; + envVars[envNdx].active = false; + } + } + + /* Enlarge environment. */ + envNdx = envVarsTotal; + if (!__enlarge_env()) + return (-1); + + /* Create environment entry. */ + envVars[envNdx].name = string; + envVars[envNdx].nameLen = -1; + envVars[envNdx].value = NULL; + envVars[envNdx].valueSize = -1; + envVars[envNdx].putenv = true; + envVars[envNdx].active = true; + newEnvActive++; + + return (__rebuild_environ(newEnvActive)); +} + + +/* + * Unset variable with the same name by flagging it as inactive. No variable is + * ever freed. + */ +int +unsetenv(const char *name) +{ + int envNdx; + size_t nameLen; + + /* Check for malformed name. */ + if (name == NULL || (nameLen = __strleneq(name)) == 0) { + errno = EINVAL; + return (-1); + } + + /* Initialize environment. */ + if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) + return (-1); + + /* Deactivate specified variable. */ + envNdx = envVarsTotal - 1; + if (__findenv(name, nameLen, &envNdx, true) != NULL) { + envVars[envNdx].active = false; + if (envVars[envNdx].putenv) + __remove_putenv(envNdx); + __rebuild_environ(envActive - 1); + } + + return (0); +} diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3 index 975da052b2..1d7824eca1 100644 --- a/lib/libc/stdlib/getopt.3 +++ b/lib/libc/stdlib/getopt.3 @@ -1,3 +1,5 @@ +.\" $NetBSD: getopt.3,v 1.31 2003/09/23 10:26:54 wiz Exp $ +.\" .\" Copyright (c) 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -9,10 +11,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +28,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)getopt.3 8.5 (Berkeley) 4/27/95 -.\" $FreeBSD: src/lib/libc/stdlib/getopt.3,v 1.11.2.8 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/getopt.3,v 1.26 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/getopt.3,v 1.5 2006/05/26 19:39:37 swildner Exp $ .\" .Dd April 27, 1995 @@ -44,12 +42,12 @@ .Sh SYNOPSIS .In unistd.h .Vt extern char *optarg ; -.Vt extern int optind ; -.Vt extern int optopt ; -.Vt extern int opterr ; -.Vt extern int optreset ; +.Vt extern int optind ; +.Vt extern int optopt ; +.Vt extern int opterr ; +.Vt extern int optreset ; .Ft int -.Fn getopt "int argc" "char * const *argv" "const char *optstring" +.Fn getopt "int argc" "char * const argv[]" "const char *optstring" .Sh DESCRIPTION The .Fn getopt @@ -98,7 +96,7 @@ saves the last option character returned by .Fn getopt . .Pp -The variable +The variables .Va opterr and .Va optind @@ -123,12 +121,7 @@ must be reinitialized. .Pp The .Fn getopt -function -returns \-1 -when the argument list is exhausted, or -.Ql ?\& -if a non-recognized -option is encountered. +function returns \-1 when the argument list is exhausted. The interpretation of options in the argument list may be cancelled by the option .Ql -- @@ -139,8 +132,36 @@ When all options have been processed (i.e., up to the first non-option argument), .Fn getopt returns \-1. +.Sh RETURN VALUES +The +.Fn getopt +function returns the next known option character in +.Fa optstring . +If +.Fn getopt +encounters a character not found in +.Fa optstring +or if it detects a missing option argument, +it returns +.Ql \&? +(question mark). +If +.Fa optstring +has a leading +.Ql \&: +then a missing option argument causes +.Ql \&: +to be returned instead of +.Ql \&? . +In either case, the variable +.Va optopt +is set to the character that caused the error. +The +.Fn getopt +function returns \-1 when the argument list is exhausted. .Sh EXAMPLES .Bd -literal -compact +#include int bflag, ch, fd; bflag = 0; @@ -150,8 +171,11 @@ while ((ch = getopt(argc, argv, "bf:")) != -1) { bflag = 1; break; case 'f': - if ((fd = open(optarg, O_RDONLY, 0)) < 0) - err(1, "%s", optarg); + if ((fd = open(optarg, O_RDONLY, 0)) \*[Lt] 0) { + fprintf(stderr, + "myname: %s: %s\en", optarg, strerror(errno)); + exit(1); + } break; default: usage(); @@ -164,17 +188,17 @@ argv += optind; If the .Fn getopt function encounters a character not found in the string -.Va optstring +.Fa optstring or detects a missing option argument it writes an error message to the -.Em stderr +.Dv stderr and returns -.Ql ?\& . +.Ql \&? . Setting .Va opterr to a zero will disable these error messages. If -.Va optstring +.Fa optstring has a leading .Ql \&: then a missing option argument causes a @@ -183,9 +207,12 @@ to be returned in addition to suppressing any error messages. .Pp Option arguments are allowed to begin with .Dq Li \- ; -this is reasonable but -reduces the amount of error checking possible. -.Sh EXTENSIONS +this is reasonable but reduces the amount of error checking possible. +.Sh SEE ALSO +.Xr getopt 1 , +.Xr getopt_long 3 , +.Xr getsubopt 3 +.Sh STANDARDS The .Va optreset variable was added to make it possible to call the @@ -227,10 +254,20 @@ as an option flag. This practice is wrong, and should not be used in any current development. It is provided for backward compatibility .Em only . +Care should be taken not to use +.Ql \&- +as the first character in +.Fa optstring +to avoid a semantic conflict with +.Tn GNU +.Fn getopt , +which assigns different meaning to an +.Fa optstring +that begins with a +.Ql \&- . By default, a single dash causes .Fn getopt to return \-1. -This is, we believe, compatible with System V. .Pp It is also possible to handle digits as option letters. This allows @@ -241,9 +278,10 @@ as an option. This practice is wrong, and should not be used in any current development. It is provided for backward compatibility .Em only . -The following code fragment works in most (but not all) cases. +The following code fragment works in most cases. .Bd -literal -offset indent -int length; +int ch; +long length; char *p, *ep; while ((ch = getopt(argc, argv, "0123456789")) != -1) { @@ -251,16 +289,17 @@ while ((ch = getopt(argc, argv, "0123456789")) != -1) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': p = argv[optind - 1]; - if (p[0] == '-' && p[1] == ch && !p[2]) - length = strtol(++p, &ep, 10); - else if (argv[optind] && argv[optind][1] == ch) { + if (p[0] == '-' \*[Am]\*[Am] p[1] == ch \*[Am]\*[Am] !p[2]) { + length = ch - '0'; + ep = ""; + } else if (argv[optind] \*[Am]\*[Am] argv[optind][1] == ch) { length = strtol((p = argv[optind] + 1), - &ep, 10); + \*[Am]ep, 10); optind++; optreset = 1; } else usage(); - if (*ep != '\0') + if (*ep != '\e0') errx(EX_USAGE, "illegal number -- %s", p); break; } diff --git a/lib/libc/stdlib/getopt.c b/lib/libc/stdlib/getopt.c index ad841beaca..402dd3bb31 100644 --- a/lib/libc/stdlib/getopt.c +++ b/lib/libc/stdlib/getopt.c @@ -12,10 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -33,14 +29,18 @@ * SUCH DAMAGE. * * @(#)getopt.c 8.3 (Berkeley) 4/27/95 - * $FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.2.2.2 2001/08/26 03:36:04 jkoshy Exp $ + * $FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.8 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/getopt.c,v 1.7 2005/11/20 12:37:48 swildner Exp $ */ +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" + +#include "libc_private.h" int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ @@ -102,7 +102,7 @@ getopt(int nargc, char * const nargv[], const char *ostr) ++optind; if (opterr && *ostr != ':') fprintf(stderr, - "%s: illegal option -- %c\n", getprogname(), + "%s: illegal option -- %c\n", _getprogname(), optopt); return (BADCH); } @@ -128,7 +128,7 @@ getopt(int nargc, char * const nargv[], const char *ostr) if (opterr) fprintf(stderr, "%s: option requires an argument -- %c\n", - getprogname(), optopt); + _getprogname(), optopt); return (BADCH); } place = EMSG; diff --git a/lib/libc/stdlib/getopt_long.3 b/lib/libc/stdlib/getopt_long.3 index e67e8c9b17..9226a85e88 100644 --- a/lib/libc/stdlib/getopt_long.3 +++ b/lib/libc/stdlib/getopt_long.3 @@ -1,5 +1,5 @@ +.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch Exp $ .\" $NetBSD: getopt_long.3,v 1.14 2003/08/07 16:43:40 agc Exp $ -.\" $DragonFly: src/lib/libc/stdlib/getopt_long.3,v 1.7 2008/11/23 21:55:52 swildner Exp $ .\" .\" Copyright (c) 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,20 +29,35 @@ .\" SUCH DAMAGE. .\" .\" @(#)getopt.3 8.5 (Berkeley) 4/27/95 +.\" $FreeBSD: src/lib/libc/stdlib/getopt_long.3,v 1.13 2005/01/20 09:17:04 ru Exp $ +.\" $DragonFly: src/lib/libc/stdlib/getopt_long.3,v 1.7 2008/11/23 21:55:52 swildner Exp $ .\" -.Dd March 14, 2007 +.Dd April 1, 2000 .Dt GETOPT_LONG 3 .Os .Sh NAME -.Nm getopt_long +.Nm getopt_long , +.Nm getopt_long_only .Nd get long options from command line argument list .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In getopt.h +.Vt extern char *optarg ; +.Vt extern int optind ; +.Vt extern int optopt ; +.Vt extern int opterr ; +.Vt extern int optreset ; .Ft int -.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "struct option *long_options" "int *index" -.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "struct option *long_options" "int *index" +.Fo getopt_long +.Fa "int argc" "char * const *argv" "const char *optstring" +.Fa "const struct option *longopts" "int *longindex" +.Fc +.Ft int +.Fo getopt_long_only +.Fa "int argc" "char * const *argv" "const char *optstring" +.Fa "const struct option *longopts" "int *longindex" +.Fc .Sh DESCRIPTION The .Fn getopt_long @@ -53,11 +68,14 @@ The .Fn getopt_long function provides a superset of the functionality of .Xr getopt 3 . +The .Fn getopt_long +function can be used in two ways. -In the first way, every long option understood by the program has a -corresponding short option, and the option structure is only used to -translate from long options to short options. +In the first way, every long option understood +by the program has a corresponding short option, and the option +structure is only used to translate from long options to short +options. When used in this fashion, .Fn getopt_long behaves identically to @@ -66,18 +84,18 @@ This is a good way to add long option processing to an existing program with the minimum of rewriting. .Pp In the second mechanism, a long option sets a flag in the -.Fa option +.Vt option structure passed, or will store a pointer to the command line argument in the -.Fa option +.Vt option structure passed to it for options that take arguments. -Additionally, the long option's argument may be specified as a single -argument with an equal sign, e.g. -.Bd -literal -myprogram --myoption=somevalue -.Ed +Additionally, +the long option's argument may be specified as a single argument with +an equal sign, e.g., +.Pp +.Dl "myprogram --myoption=somevalue" .Pp -When a long option is processed the call to +When a long option is processed, the call to .Fn getopt_long will return 0. For this reason, long option processing without @@ -86,13 +104,15 @@ shortcuts is not backwards compatible with .Pp It is possible to combine these methods, providing for long options processing with short option equivalents for some options. -Less frequently used options would be processed as long options only. +Less +frequently used options would be processed as long options only. .Pp The .Fn getopt_long -call requires a structure to be initialized describing the long options. +call requires a structure to be initialized describing the long +options. The structure is: -.Bd -literal +.Bd -literal -offset indent struct option { char *name; int has_arg; @@ -102,59 +122,58 @@ struct option { .Ed .Pp The -.Fa name +.Va name field should contain the option name without the leading double dash. .Pp The -.Fa has_arg +.Va has_arg field should be one of: -.Bl -tag -width "optional_argument" -.It Li no_argument -no argument to the option is expect. -.It Li required_argument -an argument to the option is required. -.It Li optional_argument +.Pp +.Bl -tag -width ".Dv optional_argument" -offset indent -compact +.It Dv no_argument +no argument to the option is expect +.It Dv required_argument +an argument to the option is required +.It Dv optional_argument an argument to the option may be presented. .El .Pp If -.Fa flag +.Va flag is not .Dv NULL , -then the integer pointed to by it will be set to the value in the -.Fa val +then the integer pointed to by it will be set to the +value in the +.Va val field. If the -.Fa flag +.Va flag field is .Dv NULL , then the -.Fa val +.Va val field will be returned. Setting -.Fa flag +.Va flag to .Dv NULL and setting -.Fa val +.Va val to the corresponding short option will make this function act just like .Xr getopt 3 . .Pp If the -.Fa index +.Fa longindex field is not .Dv NULL , -the integer it points to will be set to the index of the long option -in the -.Fa long_options -array. +then the integer pointed to by it will be set to the index of the long +option relative to +.Fa longopts . .Pp The last element of the -.Fa long_options -array has to be filled with zeroes (see -.Sx EXAMPLES -section). +.Fa longopts +array has to be filled with zeroes. .Pp The .Fn getopt_long_only @@ -168,126 +187,54 @@ If an option starting with .Ql - does not match a long option but does match a single-character option, the single-character option is returned. -Note that the +.Sh RETURN VALUES +If the +.Fa flag +field in +.Vt "struct option" +is +.Dv NULL , +.Fn getopt_long +and .Fn getopt_long_only -function is deprecated. -New programs should use -.Fn getopt_long . -.Sh IMPLEMENTATION DIFFERENCES -This section describes differences to the GNU implementation -found in glibc-2.1.3: -.Bl -tag -width "xxx" -.It Li o -handling of - as first char of option string in presence of -environment variable POSIXLY_CORRECT: -.Bl -tag -width "NetBSD" -.It Li GNU -ignores POSIXLY_CORRECT and returns non-options as -arguments to option '\e1'. -.It Li NetBSD -honors POSIXLY_CORRECT and stops at the first non-option. -.El -.It Li o -handling of :: in options string in presence of POSIXLY_CORRECT: -.Bl -tag -width "NetBSD" -.It Li Both -GNU and -.Nx -ignore POSIXLY_CORRECT here and take :: to -mean the preceding option takes an optional argument. -.El -.It Li o -return value in case of missing argument if first character -(after + or -) in option string is not ':': -.Bl -tag -width "NetBSD" -.It Li GNU -returns '?' -.It NetBSD -returns ':' (since -.Nx Ap s -.Fn getopt -does). -.El -.It Li o -handling of --a in -.Fn getopt : -.Bl -tag -width "NetBSD" -.It Li GNU -parses this as option '-', option 'a'. -.It Li NetBSD -parses this as '--', and returns \-1 (ignoring the a). -(Because the original -.Fn getopt -does.) -.El -.It Li o -setting of optopt for long options with flag != -.Dv NULL : -.Bl -tag -width "NetBSD" -.It Li GNU -sets optopt to val. -.It Li NetBSD -sets optopt to 0 (since val would never be returned). -.El -.It Li o -handling of -W with W; in option string in -.Fn getopt -(not -.Fn getopt_long ) : -.Bl -tag -width "NetBSD" -.It Li GNU -causes a segfault. -.It Li NetBSD -returns \-1, with optind pointing past the argument of -W -(as if `-W arg' were `--arg', and thus '--' had been found). -.\" How should we treat W; in the option string when called via -.\" getopt? Ignore the ';' or treat it as a ':'? Issue a warning? -.El -.It Li o -setting of optarg for long options without an argument that are -invoked via -W (W; in option string): -.Bl -tag -width "NetBSD" -.It Li GNU -sets optarg to the option name (the argument of -W). -.It Li NetBSD -sets optarg to -.Dv NULL -(the argument of the long option). -.El -.It Li o -handling of -W with an argument that is not (a prefix to) a known -long option (W; in option string): -.Bl -tag -width "NetBSD" -.It Li GNU -returns -W with optarg set to the unknown option. -.It Li NetBSD -treats this as an error (unknown option) and returns '?' with -optopt set to 0 and optarg set to -.Dv NULL -(as GNU's man page documents). -.El -.It Li o -The error messages are different. -.It Li o -.Nx -does not permute the argument vector at the same points in -the calling sequence as GNU does. -The aspects normally used by the caller -(ordering after \-1 is returned, value of optind relative -to current positions) are the same, though. -(We do fewer variable swaps.) +return the value specified in the +.Fa val +field, which is usually just the corresponding short option. +If +.Fa flag +is not +.Dv NULL , +these functions return 0 and store +.Fa val +in the location pointed to by +.Fa flag . +These functions return +.Ql \&: +if there was a missing option argument, +.Ql \&? +if the user specified an unknown or ambiguous option, and +\-1 when the argument list has been exhausted. +.Sh ENVIRONMENT +.Bl -tag -width ".Ev POSIXLY_CORRECT" +.It Ev POSIXLY_CORRECT +If set, option processing stops when the first non-option is found and +a leading +.Ql - +or +.Ql + +in the +.Fa optstring +is ignored. .El .Sh EXAMPLES .Bd -literal -compact -extern char *optarg; -extern int optind; int bflag, ch, fd; int daggerset; /* options descriptor */ static struct option longopts[] = { - { "buffy", no_argument, 0, 'b' }, - { "fluoride", required_argument, 0, 'f' }, + { "buffy", no_argument, NULL, 'b' }, + { "fluoride", required_argument, NULL, 'f' }, { "daggerset", no_argument, \*[Am]daggerset, 1 }, { NULL, 0, NULL, 0 } }; @@ -299,31 +246,262 @@ while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1) bflag = 1; break; case 'f': - if ((fd = open(optarg, O_RDONLY, 0)) \*[Lt] 0) { - (void)fprintf(stderr, - "myname: %s: %s\en", optarg, strerror(errno)); - exit(1); - } + if ((fd = open(optarg, O_RDONLY, 0)) == -1) + err(1, "unable to open %s", optarg); break; case 0: - if(daggerset) { + if (daggerset) { fprintf(stderr,"Buffy will use her dagger to " - "apply fluoride to dracula's teeth\en"); + "apply fluoride to dracula's teeth\en"); } break; - case '?': default: usage(); } argc -= optind; argv += optind; .Ed +.Sh IMPLEMENTATION DIFFERENCES +This section describes differences to the +.Tn GNU +implementation +found in glibc-2.1.3: +.Bl -bullet +.\" .It +.\" Handling of +.\" .Ql - +.\" as first char of option string in presence of +.\" environment variable +.\" .Ev POSIXLY_CORRECT : +.\" .Bl -tag -width ".Bx" +.\" .It Tn GNU +.\" ignores +.\" .Ev POSIXLY_CORRECT +.\" and returns non-options as +.\" arguments to option '\e1'. +.\" .It Bx +.\" honors +.\" .Ev POSIXLY_CORRECT +.\" and stops at the first non-option. +.\" .El +.\" .It +.\" Handling of +.\" .Ql - +.\" within the option string (not the first character): +.\" .Bl -tag -width ".Bx" +.\" .It Tn GNU +.\" treats a +.\" .Ql - +.\" on the command line as a non-argument. +.\" .It Bx +.\" a +.\" .Ql - +.\" within the option string matches a +.\" .Ql - +.\" (single dash) on the command line. +.\" This functionality is provided for backward compatibility with +.\" programs, such as +.\" .Xr su 1 , +.\" that use +.\" .Ql - +.\" as an option flag. +.\" This practice is wrong, and should not be used in any current development. +.\" .El +.\" .It +.\" Handling of +.\" .Ql :: +.\" in options string in presence of +.\" .Ev POSIXLY_CORRECT : +.\" .Bl -tag -width ".Bx" +.\" .It Both +.\" .Tn GNU +.\" and +.\" .Bx +.\" ignore +.\" .Ev POSIXLY_CORRECT +.\" here and take +.\" .Ql :: +.\" to +.\" mean the preceding option takes an optional argument. +.\" .El +.\" .It +.\" Return value in case of missing argument if first character +.\" (after +.\" .Ql + +.\" or +.\" .Ql - ) +.\" in option string is not +.\" .Ql \&: : +.\" .Bl -tag -width ".Bx" +.\" .It Tn GNU +.\" returns +.\" .Ql \&? +.\" .It Bx +.\" returns +.\" .Ql \&: +.\" (since +.\" .Bx Ns 's +.\" .Fn getopt +.\" does). +.\" .El +.\" .It +.\" Handling of +.\" .Ql --a +.\" in getopt: +.\" .Bl -tag -width ".Bx" +.\" .It Tn GNU +.\" parses this as option +.\" .Ql - , +.\" option +.\" .Ql a . +.\" .It Bx +.\" parses this as +.\" .Ql -- , +.\" and returns \-1 (ignoring the +.\" .Ql a ) . +.\" (Because the original +.\" .Fn getopt +.\" does.) +.\" .El +.It +Setting of +.Va optopt +for long options with +.Va flag +!= +.Dv NULL : +.Bl -tag -width ".Bx" +.It Tn GNU +sets +.Va optopt +to +.Va val . +.It Bx +sets +.Va optopt +to 0 (since +.Va val +would never be returned). +.El +.\" .It +.\" Handling of +.\" .Ql -W +.\" with +.\" .Ql W; +.\" in option string in +.\" .Fn getopt +.\" (not +.\" .Fn getopt_long ) : +.\" .Bl -tag -width ".Bx" +.\" .It Tn GNU +.\" causes a segfault. +.\" .It Bx +.\" no special handling is done; +.\" .Ql W; +.\" is interpreted as two separate options, neither of which take an argument. +.\" .El +.It +Setting of +.Va optarg +for long options without an argument that are +invoked via +.Ql -W +.Ql ( W; +in option string): +.Bl -tag -width ".Bx" +.It Tn GNU +sets +.Va optarg +to the option name (the argument of +.Ql -W ) . +.It Bx +sets +.Va optarg +to +.Dv NULL +(the argument of the long option). +.El +.It +Handling of +.Ql -W +with an argument that is not (a prefix to) a known +long option +.Ql ( W; +in option string): +.Bl -tag -width ".Bx" +.It Tn GNU +returns +.Ql -W +with +.Va optarg +set to the unknown option. +.It Bx +treats this as an error (unknown option) and returns +.Ql \&? +with +.Va optopt +set to 0 and +.Va optarg +set to +.Dv NULL +(as +.Tn GNU Ns 's +man page documents). +.El +.\" .It +.\" The error messages are different. +.It +.Bx +does not permute the argument vector at the same points in +the calling sequence as +.Tn GNU +does. +The aspects normally used by +the caller (ordering after \-1 is returned, value of +.Va optind +relative +to current positions) are the same, though. +(We do fewer variable swaps.) +.El .Sh SEE ALSO .Xr getopt 3 .Sh HISTORY The .Fn getopt_long -function first appeared in GNU libiberty. +and +.Fn getopt_long_only +functions first appeared in +.Tn GNU +libiberty. The first -.Nx -implementation appeared in 1.5. +.Bx +implementation of +.Fn getopt_long +appeared in +.Nx 1.5 , +the first +.Bx +implementation of +.Fn getopt_long_only +in +.Ox 3.3 . +.Fx +first included +.Fn getopt_long +in +.Fx 5.0 , +.Fn getopt_long_only +in +.Fx 5.2 . +.Sh BUGS +The +.Fa argv +argument is not really +.Vt const +as its elements may be permuted (unless +.Ev POSIXLY_CORRECT +is set). +.Pp +The implementation can completely replace +.Xr getopt 3 , +but right now we are using separate code. diff --git a/lib/libc/stdlib/getopt_long.c b/lib/libc/stdlib/getopt_long.c index 68e6b1484b..e27326f231 100644 --- a/lib/libc/stdlib/getopt_long.c +++ b/lib/libc/stdlib/getopt_long.c @@ -1,6 +1,25 @@ -/* $NetBSD: getopt_long.c,v 1.16 2003/10/27 00:12:42 lukem Exp $ */ -/* $DragonFly: src/lib/libc/stdlib/getopt_long.c,v 1.14 2005/11/20 12:37:48 swildner Exp $ */ +/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. @@ -35,19 +54,21 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.15 2006/09/23 14:48:31 ache Exp $ + * $DragonFly: src/lib/libc/stdlib/getopt_long.c,v 1.14 2005/11/20 12:37:48 swildner Exp $ */ -#include - #include #include #include #include #include -/* XXX BOOTSTRAPPING */ -#ifndef __DECONST -#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) +#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ + +#if 0 /* we prefer to keep our getopt(3) */ +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #endif #ifdef REPLACE_GETOPT @@ -58,28 +79,33 @@ int optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #endif -#define IGNORE_FIRST (*options == '-' || *options == '+') -#define PRINT_ERROR ((opterr) && ((*options != ':') \ - || (IGNORE_FIRST && options[1] != ':'))) -#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) -#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) -/* XXX: GNU ignores PC if *options == '-' */ -#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ -#define BADCH (int)'?' -#define BADARG ((IGNORE_FIRST && options[1] == ':') \ - || (*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -static int getopt_internal(int, char * const *, const char *, int); -static int getopt_internal_short(int, char * const *, const char *, int); -static int getopt_long_internal(int, char * const *, const char *, - const struct option *, int *, int); +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +#ifdef GNU_COMPATIBLE +#define NO_PREFIX (-1) +#define D_PREFIX 0 +#define DD_PREFIX 1 +#define W_PREFIX 2 +#endif + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int, int); static int gcd(int, int); static void permute_args(int, int, int, char * const *); -static char EMSG[] = {0}; static char *place = EMSG; /* option letter processing */ /* XXX: set optreset to 1 rather than these two */ @@ -88,12 +114,21 @@ static int nonopt_end = -1; /* first option after non options (for permute) */ /* Error messages */ static const char recargchar[] = "option requires an argument -- %c"; +static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ +#ifdef GNU_COMPATIBLE +static int dash_prefix = NO_PREFIX; +static const char gnuoptchar[] = "invalid option -- %c"; + +static const char recargstring[] = "option `%s%s' requires an argument"; +static const char ambig[] = "option `%s%.*s' is ambiguous"; +static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; +static const char illoptstring[] = "unrecognized option `%s%s'"; +#else static const char recargstring[] = "option requires an argument -- %s"; static const char ambig[] = "ambiguous option -- %.*s"; static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptchar[] = "unknown option -- %c"; static const char illoptstring[] = "unknown option -- %s"; - +#endif /* * Compute the greatest common divisor of a and b. @@ -109,8 +144,8 @@ gcd(int a, int b) b = c; c = a % b; } - - return b; + + return (b); } /* @@ -151,24 +186,213 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, } /* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too, int flags) +{ + char *current_argv, *has_equal; +#ifdef GNU_COMPATIBLE + char *current_dash; +#endif + size_t current_argv_len; + int i, match, exact_match, second_partial_match; + + current_argv = place; +#ifdef GNU_COMPATIBLE + switch (dash_prefix) { + case D_PREFIX: + current_dash = "-"; + break; + case DD_PREFIX: + current_dash = "--"; + break; + case W_PREFIX: + current_dash = "-W "; + break; + default: + current_dash = ""; + break; + } +#endif + match = -1; + exact_match = 0; + second_partial_match = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + exact_match = 1; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* first partial match */ + match = i; + else if ((flags & FLAG_LONGONLY) || + long_options[i].has_arg != + long_options[match].has_arg || + long_options[i].flag != long_options[match].flag || + long_options[i].val != long_options[match].val) + second_partial_match = 1; + } + if (!exact_match && second_partial_match) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; +#ifdef GNU_COMPATIBLE + return (BADCH); +#else + return (BADARG); +#endif + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. - * Returns -2 if -- is found (can be long option or end of options marker). */ static int getopt_internal(int nargc, char * const *nargv, const char *options, - int long_support) + const struct option *long_options, int *idx, int flags) { - optarg = NULL; + char *oli; /* option letter list index */ + int optchar, short_too; + int posixly_correct; /* no static, can be changed on the fly */ + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); +#ifdef GNU_COMPATIBLE + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; +#else + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; +#endif + if (*options == '+' || *options == '-') + options++; /* - * XXX Some programs (like rsyncd) expect to be able to - * XXX re-initialize optind to 0 and have getopt_long(3) - * XXX properly function again. Work around this braindamage. + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. */ if (optind == 0) - optind = 1; + optind = optreset = 1; + optarg = NULL; if (optreset) nonopt_start = nonopt_end = -1; start: @@ -190,29 +414,29 @@ start: optind = nonopt_start; } nonopt_start = nonopt_end = -1; - return -1; + return (-1); } - place = nargv[optind]; - if ((*place == '-') && (place[1] == '\0') && long_support == 0) - return -1; - if ((*place != '-') || - ((*place == '-') && (place[1] == '\0') && long_support != 0)) { - /* found non-option */ - place = EMSG; - if (IN_ORDER) { + if (*(place = nargv[optind]) != '-' || +#ifdef GNU_COMPATIBLE + place[1] == '\0') { +#else + (place[1] == '\0' && strchr(options, '-') == NULL)) { +#endif + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { /* - * GNU extension: + * GNU extension: * return non-option as argument to option 1 */ optarg = nargv[optind++]; - return INORDER; + return (INORDER); } - if (!PERMUTE) { + if (!(flags & FLAG_PERMUTE)) { /* - * if no permutation wanted, stop parsing - * at first non-option + * If no permutation wanted, stop parsing + * at first non-option. */ - return -1; + return (-1); } /* do permutation */ if (nonopt_start == -1) @@ -230,72 +454,97 @@ start: } if (nonopt_start != -1 && nonopt_end == -1) nonopt_end = optind; - if (place[1] && *++place == '-') { /* found "--" */ - if (place[1] == '\0') { - ++optind; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return -1; - } else if (long_support) { - place++; - return -2; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; } + nonopt_start = nonopt_end = -1; + return (-1); } } - if (long_support == 2 && (place[1] || strchr(options, *place) == NULL)) - return -3; - return getopt_internal_short(nargc, nargv, options, long_support); -} -static int -getopt_internal_short(int nargc, char * const *nargv, const char *options, - int long_support) -{ - const char *oli; /* option letter list index */ - int optchar; + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; +#ifdef GNU_COMPATIBLE + dash_prefix = D_PREFIX; +#endif + if (*place == '-') { + place++; /* --foo long option */ +#ifdef GNU_COMPATIBLE + dash_prefix = DD_PREFIX; +#endif + } else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ - if ((optchar = (int)*place++) == (int)':' || - (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { - /* option letter unknown or ':' */ - if (PRINT_ERROR) { - if (long_support == 2) - warnx(illoptstring, --place); - else - warnx(illoptchar, optchar); - } - if (long_support == 2) + optchar = parse_long_options(nargv, options, long_options, + idx, short_too, flags); + if (optchar != -1) { place = EMSG; - if (*place == 0) + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) ++optind; +#ifdef GNU_COMPATIBLE + if (PRINT_ERROR) + warnx(posixly_correct ? illoptchar : gnuoptchar, + optchar); +#else + if (PRINT_ERROR) + warnx(illoptchar, optchar); +#endif optopt = optchar; - return BADCH; + return (BADCH); } - if (long_support && optchar == 'W' && oli[1] == ';') { + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { /* -W long-option */ - if (*place) - return -2; - - if (++optind >= nargc) { /* no arg */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; - return BADARG; + return (BADARG); } else /* white space */ place = nargv[optind]; - /* - * Handle -W arg the same as --arg (which causes getopt to - * stop parsing). - */ - return -2; +#ifdef GNU_COMPATIBLE + dash_prefix = W_PREFIX; +#endif + optchar = parse_long_options(nargv, options, long_options, + idx, 0, flags); + place = EMSG; + return (optchar); } if (*++oli != ':') { /* doesn't take argument */ if (!*place) @@ -304,14 +553,13 @@ getopt_internal_short(int nargc, char * const *nargv, const char *options, optarg = NULL; if (*place) /* no white space */ optarg = place; - /* XXX: disable test for :: if PC? (GNU doesn't) */ else if (oli[1] != ':') { /* arg not optional */ if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; - return BADARG; + return (BADARG); } else optarg = nargv[optind]; } @@ -319,129 +567,7 @@ getopt_internal_short(int nargc, char * const *nargv, const char *options, ++optind; } /* dump back option letter */ - return optchar; -} - -static int -getopt_long_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int long_only) -{ - int retval; - - /* idx may be NULL */ - - retval = getopt_internal(nargc, nargv, options, long_only ? 2 : 1); -recheck: - if (retval == -2 || retval == -3) { - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; - - current_argv = place; - match = -1; - - optind++; - place = EMSG; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == - (unsigned)current_argv_len) { - /* exact match */ - match = i; - break; - } - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return BADCH; - } - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of - * flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return BADARG; - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use - * next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' - * indicates no error should be generated - */ - if (PRINT_ERROR) - warnx(recargstring, current_argv); - /* - * XXX: GNU sets optopt to val regardless - * of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return BADARG; - } - } else if (retval == -3) { - --optind; - place = current_argv; - retval = getopt_internal_short(nargc, nargv, - options, long_only ? 2 : 1); - goto recheck; - } else { /* unknown option */ - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return BADCH; - } - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - retval = 0; - } else - retval = long_options[match].val; - if (idx) - *idx = match; - } - return retval; + return (optchar); } #ifdef REPLACE_GETOPT @@ -449,38 +575,46 @@ recheck: * getopt -- * Parse argc/argv argument vector. * - * [eventually this will replace the real getopt] + * [eventually this will replace the BSD getopt] */ int getopt(int nargc, char * const *nargv, const char *options) { - return getopt_internal(nargc, nargv, options, 0); + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } -#endif +#endif /* REPLACE_GETOPT */ /* * getopt_long -- * Parse argc/argv argument vector. */ - int getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) + const struct option *long_options, int *idx) { - return getopt_long_internal(nargc, nargv, options, long_options, - idx, 0); + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); } /* * getopt_long_only -- * Parse argc/argv argument vector. - * Prefers long options over short options for single dash arguments. */ - int getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) + const struct option *long_options, int *idx) { - return getopt_long_internal(nargc, nargv, options, long_options, - idx, 1); + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); } diff --git a/lib/libc/stdlib/getsubopt.3 b/lib/libc/stdlib/getsubopt.3 index 059a751d2a..e46749591e 100644 --- a/lib/libc/stdlib/getsubopt.3 +++ b/lib/libc/stdlib/getsubopt.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93 -.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.5.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.11 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/getsubopt.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd June 9, 1993 @@ -42,7 +38,7 @@ .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.In unistd.h +.In stdlib.h .Vt extern char *suboptarg ; .Ft int .Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep" diff --git a/lib/libc/stdlib/getsubopt.c b/lib/libc/stdlib/getsubopt.c index fa0f0eb335..57faadb481 100644 --- a/lib/libc/stdlib/getsubopt.c +++ b/lib/libc/stdlib/getsubopt.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -30,14 +26,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/lib/libc/stdlib/getsubopt.c,v 1.4 2005/11/20 12:37:48 swildner Exp $ - * * @(#)getsubopt.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/getsubopt.c,v 1.7 2007/01/09 00:28:10 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/getsubopt.c,v 1.4 2005/11/20 12:37:48 swildner Exp $ */ -#include -#include #include +#include /* * The SVID interface to getsubopt provides no way of figuring out which diff --git a/lib/libc/stdlib/hcreate.3 b/lib/libc/stdlib/hcreate.3 index 5d3126951b..cfa5991810 100644 --- a/lib/libc/stdlib/hcreate.3 +++ b/lib/libc/stdlib/hcreate.3 @@ -1,7 +1,35 @@ -.\" $FreeBSD: src/lib/libc/stdlib/hcreate.3,v 1.2.2.2 2003/04/05 13:53:05 dwmalone Exp $ +.\"- +.\" Copyright (c) 1999 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Klaus Klein. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libc/stdlib/hcreate.3,v 1.7 2008/07/06 17:03:37 danger Exp $ .\" $DragonFly: src/lib/libc/stdlib/hcreate.3,v 1.5 2006/05/26 19:39:37 swildner Exp $ .\" -.Dd May 8, 2001 +.Dd July 6, 2008 .Os .Dt HCREATE 3 .Sh NAME @@ -114,8 +142,10 @@ is called. .Sh RETURN VALUES The .Fn hcreate -function returns 0 if it cannot allocate sufficient space for the table; -otherwise, it returns non-zero. +function returns 0 if the table creation failed and the global variable +.Va errno +is set to indicate the error; +otherwise, a non-zero value is returned. .Pp The .Fn hdestroy @@ -202,6 +232,8 @@ functions may fail if: .Bl -tag -width Er .It Bq Er ENOMEM Insufficient storage space is available. +.It Bq Er EINVAL +A table already exists. .El .Sh SEE ALSO .Xr bsearch 3 , diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c index 4ded5aef9a..2d542e8818 100644 --- a/lib/libc/stdlib/hcreate.c +++ b/lib/libc/stdlib/hcreate.c @@ -32,7 +32,7 @@ * <> * * $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ - * $FreeBSD: src/lib/libc/stdlib/hcreate.c,v 1.1.2.2 2001/10/02 11:22:56 ru Exp $ + * $FreeBSD: src/lib/libc/stdlib/hcreate.c,v 1.4 2008/07/06 11:31:20 danger Exp $ * $DragonFly: src/lib/libc/stdlib/hcreate.c,v 1.2 2003/06/17 04:26:46 dillon Exp $ */ @@ -48,8 +48,6 @@ * nobody had a copy in the office, so... */ -#include - #include #include #include @@ -89,7 +87,7 @@ hcreate(size_t nel) size_t idx; unsigned int p2; - /* Make sure this this isn't called when a table already exists. */ + /* Make sure this is not called when a table already exists. */ if (htable != NULL) { errno = EINVAL; return 0; @@ -99,11 +97,11 @@ hcreate(size_t nel) if (nel < MIN_BUCKETS) nel = MIN_BUCKETS; - /* If it's too large, cap it. */ + /* If it is too large, cap it. */ if (nel > MAX_BUCKETS) nel = MAX_BUCKETS; - /* If it's is not a power of two in size, round up. */ + /* If it is not a power of two in size, round up. */ if ((nel & (nel - 1)) != 0) { for (p2 = 0; nel != 0; p2++) nel >>= 1; diff --git a/lib/libc/stdlib/heapsort.c b/lib/libc/stdlib/heapsort.c index 71845dee39..02d3fd01a9 100644 --- a/lib/libc/stdlib/heapsort.c +++ b/lib/libc/stdlib/heapsort.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -33,9 +29,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/lib/libc/stdlib/heapsort.c,v 1.5 2005/11/20 12:37:48 swildner Exp $ - * * @(#)heapsort.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/heapsort.c,v 1.6 2008/01/13 02:11:10 das Exp $ + * $DragonFly: src/lib/libc/stdlib/heapsort.c,v 1.5 2005/11/20 12:37:48 swildner Exp $ */ #include @@ -141,7 +137,7 @@ int heapsort(void *vbase, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { - int cnt, i, j, l; + size_t cnt, i, j, l; char tmp, *tmp1, *tmp2; char *base, *k, *p, *t; diff --git a/lib/libc/stdlib/insque.3 b/lib/libc/stdlib/insque.3 new file mode 100644 index 0000000000..06f93bf20f --- /dev/null +++ b/lib/libc/stdlib/insque.3 @@ -0,0 +1,61 @@ +.\" +.\" Initial implementation: +.\" Copyright (c) 2002 Robert Drehmel +.\" All rights reserved. +.\" +.\" As long as the above copyright statement and this notice remain +.\" unchanged, you can do what ever you want with this file. +.\" +.\" $FreeBSD: src/lib/libc/stdlib/insque.3,v 1.3 2003/02/25 21:59:36 robert Exp $ +.\" +.Dd October 10, 2002 +.Dt INSQUE 3 +.Os +.Sh NAME +.Nm insque , +.Nm remque +.Nd doubly-linked list management +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In search.h +.Ft void +.Fn insque "void *element1" "void *pred" +.Ft void +.Fn remque "void *element" +.Sh DESCRIPTION +The +.Fn insque +and +.Fn remque +functions encapsulate the ever-repeating task of doing insertion and +removal operations on doubly linked lists. +The functions expect their +arguments to point to a structure whose first and second members are +pointers to the next and previous element, respectively. +The +.Fn insque +function also allows the +.Fa pred +argument to be a +.Dv NULL +pointer for the initialization of a new list's +head element. +.Sh STANDARDS +The +.Fn insque +and +.Fn remque +functions conform to +.St -p1003.1-2001 . +.Sh HISTORY +The +.Fn insque +and +.Fn remque +functions appeared in +.Bx 4.2 . +In +.Fx 5.0 , +they reappeared conforming to +.St -p1003.1-2001 . diff --git a/lib/libc/stdlib/insque.c b/lib/libc/stdlib/insque.c new file mode 100644 index 0000000000..d98400d9c5 --- /dev/null +++ b/lib/libc/stdlib/insque.c @@ -0,0 +1,47 @@ +/* + * Initial implementation: + * Copyright (c) 2002 Robert Drehmel + * All rights reserved. + * + * As long as the above copyright statement and this notice remain + * unchanged, you can do what ever you want with this file. + * + * $FreeBSD: src/lib/libc/stdlib/insque.c,v 1.3 2003/01/04 07:34:41 tjr Exp $ + */ + +#define _SEARCH_PRIVATE +#include +#ifdef DEBUG +#include +#else +#include /* for NULL */ +#endif + +void +insque(void *element, void *pred) +{ + struct que_elem *prev, *next, *elem; + + elem = (struct que_elem *)element; + prev = (struct que_elem *)pred; + + if (prev == NULL) { + elem->prev = elem->next = NULL; + return; + } + + next = prev->next; + if (next != NULL) { +#ifdef DEBUG + if (next->prev != prev) { + fprintf(stderr, "insque: Inconsistency detected:" + " next(%p)->prev(%p) != prev(%p)\n", + next, next->prev, prev); + } +#endif + next->prev = elem; + } + prev->next = elem; + elem->prev = prev; + elem->next = next; +} diff --git a/lib/libc/stdlib/l64a.c b/lib/libc/stdlib/l64a.c new file mode 100644 index 0000000000..d3fc949af6 --- /dev/null +++ b/lib/libc/stdlib/l64a.c @@ -0,0 +1,40 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * $NetBSD: l64a.c,v 1.13 2003/07/26 19:24:54 salo Exp $ + * $FreeBSD: src/lib/libc/stdlib/l64a.c,v 1.1 2005/12/24 22:37:59 trhodes Exp $ + */ + +#include + +char * +l64a(long value) +{ + static char buf[8]; + + l64a_r(value, buf, sizeof(buf)); + return (buf); +} + +int +l64a_r(long value, char *buffer, int buflen) +{ + long v; + int digit; + + v = value & (long)0xffffffff; + for (; v != 0 && buflen > 1; buffer++, buflen--) { + digit = v & 0x3f; + if (digit < 2) + *buffer = digit + '.'; + else if (digit < 12) + *buffer = digit + '0' - 2; + else if (digit < 38) + *buffer = digit + 'A' - 12; + else + *buffer = digit + 'a' - 38; + v >>= 6; + } + return (v == 0 ? 0 : -1); +} diff --git a/lib/libc/stdlib/labs.3 b/lib/libc/stdlib/labs.3 index 61597574e1..9fd70de7a0 100644 --- a/lib/libc/stdlib/labs.3 +++ b/lib/libc/stdlib/labs.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)labs.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.4.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.10 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/labs.3,v 1.3 2007/12/02 03:29:47 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd November 14, 2001 .Dt LABS 3 .Os .Sh NAME @@ -54,7 +50,7 @@ The .Fn labs function returns the absolute value of the long integer -.Ar j . +.Fa j . .Sh SEE ALSO .Xr abs 3 , .Xr cabs 3 , diff --git a/lib/libc/stdlib/labs.c b/lib/libc/stdlib/labs.c index 27d83dfaa8..a30d8ee454 100644 --- a/lib/libc/stdlib/labs.c +++ b/lib/libc/stdlib/labs.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,6 +27,7 @@ * SUCH DAMAGE. * * @(#)labs.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/labs.c,v 1.3 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/labs.c,v 1.3 2005/11/20 12:37:48 swildner Exp $ */ diff --git a/lib/libc/stdlib/ldiv.3 b/lib/libc/stdlib/ldiv.3 index 49e8266eb1..e66b68bee8 100644 --- a/lib/libc/stdlib/ldiv.3 +++ b/lib/libc/stdlib/ldiv.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)ldiv.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.4.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.10 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/ldiv.3,v 1.3 2008/01/25 23:24:31 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd November 14, 2001 .Dt LDIV 3 .Os .Sh NAME @@ -54,15 +50,15 @@ The .Fn ldiv function computes the value -.Ar num/denom +.Fa num Ns / Ns Fa denom and returns the quotient and remainder in a structure named -.Ar ldiv_t +.Vt ldiv_t that contains two -.Em long integer +.Vt long members named -.Ar quot +.Va quot and -.Ar rem . +.Va rem . .Sh SEE ALSO .Xr div 3 , .Xr imaxdiv 3 , @@ -73,4 +69,4 @@ The .Fn ldiv function conforms to -.St -isoC . +.St -isoC-99 . diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c index 49f82d1f2c..355e6b2d11 100644 --- a/lib/libc/stdlib/ldiv.c +++ b/lib/libc/stdlib/ldiv.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -34,6 +30,7 @@ * SUCH DAMAGE. * * @(#)ldiv.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/ldiv.c,v 1.3 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/ldiv.c,v 1.4 2005/11/23 08:55:59 swildner Exp $ */ diff --git a/lib/libc/stdlib/lsearch.c b/lib/libc/stdlib/lsearch.c index 42c1ca86c0..88c6b6a3f8 100644 --- a/lib/libc/stdlib/lsearch.c +++ b/lib/libc/stdlib/lsearch.c @@ -6,10 +6,10 @@ * As long as the above copyright statement and this notice remain * unchanged, you can do what ever you want with this file. * + * $FreeBSD: src/lib/libc/stdlib/lsearch.c,v 1.1 2002/10/16 14:29:22 robert Exp $ * $DragonFly: src/lib/libc/stdlib/lsearch.c,v 1.1 2008/05/19 10:06:34 corecode Exp $ */ #include -#include #define _SEARCH_PRIVATE #include diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index f65c34f1cb..71fedc08a9 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -447,8 +447,6 @@ malloc_dump(int fd) } #endif /* MALLOC_STATS */ -extern char *__progname; - static void wrterror(char *p) { diff --git a/lib/libc/stdlib/memory.3 b/lib/libc/stdlib/memory.3 index e2fc9877cd..fa5710744b 100644 --- a/lib/libc/stdlib/memory.3 +++ b/lib/libc/stdlib/memory.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)memory.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.5.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.12 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/memory.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd June 4, 1993 @@ -41,7 +37,8 @@ .Nm free , .Nm realloc , .Nm calloc , -.Nm alloca +.Nm alloca , +.Nm mmap .Nd general memory allocation operations .Sh LIBRARY .Lb libc @@ -57,11 +54,16 @@ .Fn calloc "size_t nelem" "size_t elsize" .Ft void * .Fn alloca "size_t size" +.In sys/types.h +.In sys/mman.h +.Ft void * +.Fn mmap "void * addr" "size_t len" "int prot" "int flags" "int fd" "off_t offset" .Sh DESCRIPTION These functions allocate and free memory for the calling process. They are described in the individual manual pages. .Sh SEE ALSO +.Xr mmap 2 , .Xr alloca 3 , .Xr calloc 3 , .Xr free 3 , @@ -70,5 +72,7 @@ individual manual pages. .Sh STANDARDS These functions, with the exception of .Fn alloca +and +.Fn mmap conform to .St -isoC . diff --git a/lib/libc/stdlib/merge.c b/lib/libc/stdlib/merge.c index 3a7ad9d3f2..12c5153c1b 100644 --- a/lib/libc/stdlib/merge.c +++ b/lib/libc/stdlib/merge.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -34,6 +30,7 @@ * SUCH DAMAGE. * * @(#)merge.c 8.2 (Berkeley) 2/14/94 + * $FreeBSD: src/lib/libc/stdlib/merge.c,v 1.8 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/merge.c,v 1.6 2005/11/20 12:37:48 swildner Exp $ */ @@ -100,7 +97,7 @@ mergesort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *)) { size_t i; - int sense; + int sense; int big, iflag; u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2; u_char *list2, *list1, *p2, *p, *last, **p1; diff --git a/lib/libc/stdlib/putenv.c b/lib/libc/stdlib/putenv.c deleted file mode 100644 index da524ac541..0000000000 --- a/lib/libc/stdlib/putenv.c +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)putenv.c 8.2 (Berkeley) 3/27/94 - * $DragonFly: src/lib/libc/stdlib/putenv.c,v 1.3 2005/11/20 12:37:49 swildner Exp $ - */ - -#include -#include - -int -putenv(const char *str) -{ - char *p, *equal; - int rval; - - if ((p = strdup(str)) == NULL) - return (-1); - if ((equal = index(p, '=')) == NULL) { - free(p); - return (-1); - } - *equal = '\0'; - rval = setenv(p, equal + 1, 1); - free(p); - return (rval); -} diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index a0c143ffee..cfa7338fc1 100644 --- a/lib/libc/stdlib/qsort.3 +++ b/lib/libc/stdlib/qsort.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,14 +30,15 @@ .\" SUCH DAMAGE. .\" .\" @(#)qsort.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.4.2.5 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.17 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/qsort.3,v 1.4 2006/02/17 19:35:06 swildner Exp $ .\" -.Dd June 4, 1993 +.Dd September 30, 2003 .Dt QSORT 3 .Os .Sh NAME .Nm qsort , +.Nm qsort_r , .Nm heapsort , .Nm mergesort .Nd sort functions @@ -50,11 +47,34 @@ .Sh SYNOPSIS .In stdlib.h .Ft void -.Fn qsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)" +.Fo qsort +.Fa "void *base" +.Fa "size_t nmemb" +.Fa "size_t size" +.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" +.Fc +.Ft void +.Fo qsort_r +.Fa "void *base" +.Fa "size_t nmemb" +.Fa "size_t size" +.Fa "void *thunk" +.Fa "int \*[lp]*compar\*[rp]\*[lp]void *, const void *, const void *\*[rp]" +.Fc .Ft int -.Fn heapsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)" +.Fo heapsort +.Fa "void *base" +.Fa "size_t nmemb" +.Fa "size_t size" +.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" +.Fc .Ft int -.Fn mergesort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)" +.Fo mergesort +.Fa "void *base" +.Fa "size_t nmemb" +.Fa "size_t size" +.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" +.Fc .Sh DESCRIPTION The .Fn qsort @@ -77,7 +97,9 @@ objects, the initial member of which is pointed to by .Fa base . The size of each object is specified by .Fa size . -.Fn Mergesort +The +.Fn mergesort +function behaves similarly, but .Em requires that @@ -97,33 +119,58 @@ The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. .Pp -The functions -.Fn qsort +The +.Fn qsort_r +function behaves identically to +.Fn qsort , +except that it takes an additional argument, +.Fa thunk , +which is passed unchanged as the first argument to function pointed to +.Fa compar . +This allows the comparison function to access additional +data without using global variables, and thus +.Fn qsort_r +is suitable for use in functions which must be reentrant. +.Pp +The algorithms implemented by +.Fn qsort , +.Fn qsort_r , and .Fn heapsort are .Em not stable, that is, if two members compare as equal, their order in the sorted array is undefined. -The function +The .Fn mergesort -is stable. +algorithm is stable. .Pp The .Fn qsort -function is an implementation of C.A.R. Hoare's ``quicksort'' algorithm, -a variant of partition-exchange sorting; in particular, see D.E. Knuth's -Algorithm Q. -.Fn Qsort +and +.Fn qsort_r +functions are an implementation of C.A.R. +Hoare's +.Dq quicksort +algorithm, +a variant of partition-exchange sorting; in particular, see +.An D.E. Knuth Ns 's +.%T "Algorithm Q" . +.Sy Quicksort takes O N lg N average time. This implementation uses median selection to avoid its O N**2 worst-case behavior. .Pp The .Fn heapsort -function is an implementation of J.W.J. William's ``heapsort'' algorithm, -a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H. -.Fn Heapsort +function is an implementation of +.An "J.W.J. William" Ns 's +.Dq heapsort +algorithm, +a variant of selection sorting; in particular, see +.An "D.E. Knuth" Ns 's +.%T "Algorithm H" . +.Sy Heapsort takes O N lg N worst-case time. Its .Em only @@ -139,7 +186,9 @@ requires additional memory of size .Fa nmemb * .Fa size bytes; it should be used only when space is not at a premium. -.Fn Mergesort +The +.Fn mergesort +function is optimized for data with pre-existing order; its worst case time is O N lg N; its best case is O N. .Pp @@ -154,8 +203,10 @@ untrue. .Sh RETURN VALUES The .Fn qsort -function -returns no value. +and +.Fn qsort_r +functions +return no value. .Pp .Rv -std heapsort mergesort .Sh COMPATIBILITY @@ -182,9 +233,11 @@ argument to is less than .Dq "sizeof(void *) / 2" . .It Bq Er ENOMEM -.Fn Heapsort +The +.Fn heapsort or .Fn mergesort +functions were unable to allocate memory. .El .Sh SEE ALSO @@ -215,16 +268,19 @@ were unable to allocate memory. .%P pp. 114-123, 145-149 .Re .Rs -.%A Mcilroy, P.M. +.%A McIlroy, P.M. .%T "Optimistic Sorting and Information Theoretic Complexity" .%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms" .%V January 1992 .Re .Rs .%A Bentley, J.L. +.%A McIlroy, M.D. .%T "Engineering a Sort Function" -.%J "bentley@research.att.com" -.%V January 1992 +.%J "Software--Practice and Experience" +.%V Vol. 23(11) +.%P pp. 1249-1265 +.%D November\ 1993 .Re .Sh STANDARDS The diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c index e5e6a3ee62..214b7011cb 100644 --- a/lib/libc/stdlib/qsort.c +++ b/lib/libc/stdlib/qsort.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,15 +27,19 @@ * SUCH DAMAGE. * * @(#)qsort.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.8 1999/08/28 00:01:35 peter Exp $ + * $FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15 2008/01/14 09:21:34 das Exp $ * $DragonFly: src/lib/libc/stdlib/qsort.c,v 1.5 2005/11/20 12:37:49 swildner Exp $ */ #include -typedef int cmp_t (const void *, const void *); -static inline char *med3 (char *, char *, char *, cmp_t *); -static inline void swapfunc (char *, char *, int, int); +#ifdef I_AM_QSORT_R +typedef int cmp_t(void *, const void *, const void *); +#else +typedef int cmp_t(const void *, const void *); +#endif +static inline char *med3(char *, char *, char *, cmp_t *, void *); +static inline void swapfunc(char *, char *, int, int); #define min(a, b) (a) < (b) ? a : b @@ -79,25 +79,44 @@ swapfunc(char *a, char *b, int n, int swaptype) #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) +#ifdef I_AM_QSORT_R +#define CMP(t, x, y) (cmp((t), (x), (y))) +#else +#define CMP(t, x, y) (cmp((x), (y))) +#endif + static inline char * -med3(char *a, char *b, char *c, cmp_t *cmp) +med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk +#ifndef I_AM_QSORT_R +__unused +#endif +) { - return cmp(a, b) < 0 ? - (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) - :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) + :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); } +#ifdef I_AM_QSORT_R +void +qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#else +#define thunk NULL void qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#endif { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - int d, r, swaptype, swap_cnt; + size_t d, r; + int cmp_result; + int swaptype, swap_cnt; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; @@ -108,27 +127,27 @@ loop: SWAPINIT(a, es); pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; - pl = med3(pl, pl + d, pl + 2 * d, cmp); - pm = med3(pm - d, pm, pm + d, cmp); - pn = med3(pn - 2 * d, pn - d, pn, cmp); + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); } - pm = med3(pl, pm, pn, cmp); + pm = med3(pl, pm, pn, cmp, thunk); } swap(a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { - while (pb <= pc && (r = cmp(pb, a)) <= 0) { - if (r == 0) { + while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { + if (cmp_result == 0) { swap_cnt = 1; swap(pa, pb); pa += es; } pb += es; } - while (pb <= pc && (r = cmp(pc, a)) >= 0) { - if (r == 0) { + while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { + if (cmp_result == 0) { swap_cnt = 1; swap(pc, pd); pd -= es; @@ -144,7 +163,8 @@ loop: SWAPINIT(a, es); } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; @@ -156,7 +176,11 @@ loop: SWAPINIT(a, es); r = min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) +#ifdef I_AM_QSORT_R + qsort_r(a, r / es, es, thunk, cmp); +#else qsort(a, r / es, es, cmp); +#endif if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; diff --git a/lib/libc/stdlib/qsort_r.c b/lib/libc/stdlib/qsort_r.c new file mode 100644 index 0000000000..f7c0e54f74 --- /dev/null +++ b/lib/libc/stdlib/qsort_r.c @@ -0,0 +1,8 @@ +/* + * This file is in the public domain. Originally written by Garrett + * A. Wollman. + * + * $FreeBSD: src/lib/libc/stdlib/qsort_r.c,v 1.1 2002/09/10 02:04:49 wollman Exp $ + */ +#define I_AM_QSORT_R +#include "qsort.c" diff --git a/lib/libc/stdlib/radixsort.3 b/lib/libc/stdlib/radixsort.3 index 5d77618fea..1a57076845 100644 --- a/lib/libc/stdlib/radixsort.3 +++ b/lib/libc/stdlib/radixsort.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,14 +26,15 @@ .\" SUCH DAMAGE. .\" .\" @(#)radixsort.3 8.2 (Berkeley) 1/27/94 -.\" $FreeBSD: src/lib/libc/stdlib/radixsort.3,v 1.5.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/radixsort.3,v 1.12 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/radixsort.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd January 27, 1994 .Dt RADIXSORT 3 .Os .Sh NAME -.Nm radixsort +.Nm radixsort , +.Nm sradixsort .Nd radix sort .Sh LIBRARY .Lb libc @@ -106,7 +103,10 @@ The function is not stable, but uses no additional memory. .Pp These functions are variants of most-significant-byte radix sorting; in -particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10. +particular, see +.An "D.E. Knuth" Ns 's +.%T "Algorithm R" +and section 5.2.5, exercise 10. They take linear time relative to the number of bytes in the strings. .Sh RETURN VALUES .Rv -std radixsort diff --git a/lib/libc/stdlib/radixsort.c b/lib/libc/stdlib/radixsort.c index 51c9fe9f56..aeb3c27a82 100644 --- a/lib/libc/stdlib/radixsort.c +++ b/lib/libc/stdlib/radixsort.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -33,9 +29,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/lib/libc/stdlib/radixsort.c,v 1.5 2005/11/20 12:37:49 swildner Exp $ - * * @(#)radixsort.c 8.2 (Berkeley) 4/28/95 + * $FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.8 2007/01/09 00:28:10 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/radixsort.c,v 1.5 2005/11/20 12:37:49 swildner Exp $ */ /* @@ -61,11 +57,10 @@ typedef struct { int sn, si; } stack; -static inline void simplesort - (const u_char **, int, int, const u_char *, u_int); -static void r_sort_a (const u_char **, int, int, const u_char *, u_int); -static void r_sort_b (const u_char **, - const u_char **, int, int, const u_char *, u_int); +static inline void simplesort(const u_char **, int, int, const u_char *, u_int); +static void r_sort_a(const u_char **, int, int, const u_char *, u_int); +static void r_sort_b(const u_char **, const u_char **, int, int, + const u_char *, u_int); #define THRESHOLD 20 /* Divert to simplesort(). */ #define SIZE 512 /* Default stack size. */ @@ -165,6 +160,17 @@ r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch) } /* + * Special case: if all strings have the same + * character at position i, move on to the next + * character. + */ + if (nc == 1 && count[bmin] == n) { + push(a, n, i+1); + nc = count[bmin] = 0; + continue; + } + + /* * Set top[]; push incompletely sorted bins onto stack. * top[] = pointers to last out-of-place element in bins. * count[] = counts of elements in bins. diff --git a/lib/libc/stdlib/rand.3 b/lib/libc/stdlib/rand.3 index e183a1e001..d6b8126f9b 100644 --- a/lib/libc/stdlib/rand.3 +++ b/lib/libc/stdlib/rand.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)rand.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.14 2003/09/08 19:57:15 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.16 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/rand.3,v 1.6 2007/06/29 19:34:41 swildner Exp $ .\" .Dd May 25, 1999 @@ -92,8 +88,10 @@ The .Fn sranddev function initializes a seed using the .Xr random 4 -random number device which returns good random numbers, -suitable for cryptographic use. +random number device which returns good random numbers. +However, the +.Fn rand +function still remains unsuitable for cryptographic use. .Pp The .Fn rand_r diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c index dde21aae41..4b93a35df5 100644 --- a/lib/libc/stdlib/rand.c +++ b/lib/libc/stdlib/rand.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -32,12 +28,14 @@ * * Posix rand_r function added May 1999 by Wes Peters . * - * $FreeBSD: src/lib/libc/stdlib/rand.c,v 1.15 2001/03/05 11:33:57 ache Exp $ + * @(#)rand.c 8.1 (Berkeley) 6/14/93 + * $FreeBSD: src/lib/libc/stdlib/rand.c,v 1.17 2007/12/11 20:39:32 ache Exp $ * $DragonFly: src/lib/libc/stdlib/rand.c,v 1.6 2005/11/20 14:58:40 swildner Exp $ */ #include "namespace.h" #include /* for sranddev() */ +#include #include /* for sranddev() */ #include #include /* for sranddev() */ @@ -47,8 +45,6 @@ #include #endif /* TEST */ -void sranddev(void); - static int do_rand(unsigned long *ctx) { @@ -62,7 +58,7 @@ do_rand(unsigned long *ctx) #else /* !USE_WEAK_SEEDING */ /* * Compute x = (7^5 * x) mod (2^31 - 1) - * wihout overflowing 31 bits: + * without overflowing 31 bits: * (2^31 - 1) = 127773 * (7^5) + 2836 * From "Random number generators: good ones are hard to find", * Park and Miller, Communications of the ACM, vol. 31, no. 10, @@ -115,11 +111,6 @@ srand(u_int seed) * Many programs choose the seed value in a totally predictable manner. * This often causes problems. We seed the generator using the much more * secure random(4) interface. - * - * FreeBSD chooses to use /dev/random for their seed. However, because - * of possible problems surrounding /dev/random, we use /dev/urandom for now, - * which is guaranteed not to block and will produce a "good enough" seed - * for us for the time being. */ void sranddev(void) @@ -127,7 +118,7 @@ sranddev(void) int fd, done; done = 0; - fd = _open("/dev/urandom", O_RDONLY, 0); + fd = _open("/dev/random", O_RDONLY, 0); if (fd >= 0) { if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next)) done = 1; diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3 index b29549c5b6..5ee1a3efdf 100644 --- a/lib/libc/stdlib/random.3 +++ b/lib/libc/stdlib/random.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)random.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.11.2.6 2003/06/03 19:13:16 schweikh Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.22 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/random.3,v 1.5 2007/06/29 19:34:41 swildner Exp $ .\" .Dd June 4, 1993 @@ -82,9 +78,11 @@ functions. The difference is that .Xr rand 3 produces a much less random sequence \(em in fact, the low dozen bits -generated by rand go through a cyclic pattern. All the bits generated by +generated by rand go through a cyclic pattern. +All the bits generated by .Fn random -are usable. For example, +are usable. +For example, .Sq Li random()&01 will produce a random binary value. @@ -102,7 +100,7 @@ as the seed. The .Fn srandomdev routine initializes a state array using the -.Xr urandom 4 +.Xr random 4 random number device which returns good random numbers, suitable for cryptographic use. Note that this particular seeding @@ -116,13 +114,15 @@ a fixed seed. The .Fn initstate routine allows a state array, passed in as an argument, to be initialized -for future use. The size of the state array (in bytes) is used by +for future use. +The size of the state array (in bytes) is used by .Fn initstate to decide how sophisticated a random number generator it should use \(em the more state, the better the random numbers will be. (Current "optimal" values for the amount of state information are 8, 32, 64, 128, and 256 bytes; other amounts will be rounded down to -the nearest known amount. Using less than 8 bytes will cause an error.) +the nearest known amount. +Using less than 8 bytes will cause an error.) The seed for the initialization (which specifies a starting point for the random number sequence, and provides for restarting at the same point) is also an argument. @@ -176,7 +176,7 @@ messages are printed on the standard error output. .Xr arc4random 3 , .Xr rand 3 , .Xr srand 3 , -.Xr urandom 4 +.Xr random 4 .Sh HISTORY These functions appeared in @@ -191,3 +191,6 @@ The historical implementation used to have a very weak seeding; the random sequence did not vary much with the seed. The current implementation employs a better pseudo-random number generator for the initial state calculation. +.Pp +Applications requiring cryptographic quality randomness should use +.Xr arc4random 3 . diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c index dd889ab1fe..fee7bb1bac 100644 --- a/lib/libc/stdlib/random.c +++ b/lib/libc/stdlib/random.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -30,15 +26,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/stdlib/random.c,v 1.13 2000/01/27 23:06:49 jasone Exp $ - * $DragonFly: src/lib/libc/stdlib/random.c,v 1.9 2005/11/24 17:18:30 swildner Exp $ - * * @(#)random.c 8.2 (Berkeley) 5/19/95 + * $FreeBSD: src/lib/libc/stdlib/random.c,v 1.25 2007/01/09 00:28:10 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/random.c,v 1.9 2005/11/24 17:18:30 swildner Exp $ */ #include "namespace.h" #include /* for srandomdev() */ #include /* for srandomdev() */ +#include #include #include #include /* for srandomdev() */ @@ -60,7 +56,7 @@ * congruential generator. If the amount of state information is less than * 32 bytes, a simple linear congruential R.N.G. is used. * - * Internally, the state information is treated as an array of ints; the + * Internally, the state information is treated as an array of uint32_t's; the * zeroeth element of the array is the type of R.N.G. being used (small * integer); the remainder of the array is the state information for the * R.N.G. Thus, 32 bytes of state information will give 7 ints worth of @@ -79,7 +75,7 @@ * period of the generator is approximately deg*(2**deg - 1); thus doubling * the amount of state information has a vast influence on the period of the * generator. Note: the deg*(2**deg - 1) is an approximation only good for - * large deg, when the period of the shift register is the dominant factor. + * large deg, when the period of the shift is the dominant factor. * With deg equal to seven, the period is actually much longer than the * 7*(2**7 - 1) predicted by this formula. * @@ -141,6 +137,12 @@ */ #define MAX_TYPES 5 /* max number of types above */ +#ifdef USE_WEAK_SEEDING +#define NSHUFF 0 +#else /* !USE_WEAK_SEEDING */ +#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */ +#endif /* !USE_WEAK_SEEDING */ + static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; @@ -212,10 +214,10 @@ static int rand_deg = DEG_3; static int rand_sep = SEP_3; static uint32_t *end_ptr = &randtbl[DEG_3 + 1]; -static inline long good_rand(long); +static inline uint32_t good_rand(int32_t); -static inline long -good_rand(long x) +static inline uint32_t +good_rand(int32_t x) { #ifdef USE_WEAK_SEEDING /* @@ -233,12 +235,15 @@ good_rand(long x) * Park and Miller, Communications of the ACM, vol. 31, no. 10, * October 1988, p. 1195. */ - long hi, lo; + int32_t hi, lo; + /* Can't be initialized with 0, so use another value. */ + if (x == 0) + x = 123459876; hi = x / 127773; lo = x % 127773; x = 16807 * lo - 2836 * hi; - if (x <= 0) + if (x < 0) x += 0x7fffffff; return (x); #endif /* !USE_WEAK_SEEDING */ @@ -259,19 +264,20 @@ good_rand(long x) void srandom(unsigned long x) { - int i; + int i, lim; + state[0] = (uint32_t)x; if (rand_type == TYPE_0) - state[0] = (uint32_t)x; + lim = NSHUFF; else { - state[0] = (uint32_t)x; for (i = 1; i < rand_deg; i++) - state[i] = (uint32_t)good_rand(state[i - 1]); + state[i] = good_rand(state[i - 1]); fptr = &state[rand_sep]; rptr = &state[0]; - for (i = 0; i < 10 * rand_deg; i++) - random(); + lim = 10 * rand_deg; } + for (i = 0; i < lim; i++) + random(); } /* @@ -279,7 +285,7 @@ srandom(unsigned long x) * * Many programs choose the seed value in a totally predictable manner. * This often causes problems. We seed the generator using the much more - * secure urandom(4) interface. Note that this particular seeding + * secure random(4) interface. Note that this particular seeding * procedure can generate states which are impossible to reproduce by * calling srandom() with any value, since the succeeding terms in the * state buffer are no longer derived from the LC algorithm applied to @@ -297,7 +303,7 @@ srandomdev(void) len = rand_deg * sizeof state[0]; done = 0; - fd = _open("/dev/urandom", O_RDONLY, 0); + fd = _open("/dev/random", O_RDONLY, 0); if (fd >= 0) { if (_read(fd, (void *) state, len) == (ssize_t) len) done = 1; @@ -309,7 +315,7 @@ srandomdev(void) unsigned long junk; /* XXX left uninitialized on purpose */ gettimeofday(&tv, NULL); - srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk); + srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); return; } @@ -351,12 +357,12 @@ char * initstate(unsigned long seed, char *arg_state, long n) { char *ostate = (char *)(&state[-1]); - uint32_t *int_arg_state = (uint32_t *)(void *)arg_state; + uint32_t *int_arg_state = (uint32_t *)arg_state; if (rand_type == TYPE_0) state[-1] = rand_type; else - state[-1] = MAX_TYPES * (uint32_t)(rptr - state) + rand_type; + state[-1] = MAX_TYPES * (rptr - state) + rand_type; if (n < BREAK_0) { fprintf(stderr, "random: not enough state (%ld bytes); ignored.\n", n); @@ -383,13 +389,13 @@ initstate(unsigned long seed, char *arg_state, long n) rand_deg = DEG_4; rand_sep = SEP_4; } - state = (uint32_t *) (int_arg_state + 1); /* first location */ + state = int_arg_state + 1; /* first location */ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom((uint32_t)seed); + srandom(seed); if (rand_type == TYPE_0) int_arg_state[0] = rand_type; else - int_arg_state[0] = MAX_TYPES * (uint32_t)(rptr - state) + rand_type; + int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type; return(ostate); } @@ -411,14 +417,14 @@ initstate(unsigned long seed, char *arg_state, long n) * * Returns a pointer to the old state information. * - * Note: The Sparc platform requires that arg_state begin on a long + * Note: The Sparc platform requires that arg_state begin on an int * word boundary; otherwise a bus error will occur. Even so, lint will * complain about mis-alignment, but you should disregard these messages. */ char * setstate(char *arg_state) { - uint32_t *new_state = (uint32_t *)(void *)arg_state; + uint32_t *new_state = (uint32_t *)arg_state; uint32_t type = new_state[0] % MAX_TYPES; uint32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); @@ -426,7 +432,7 @@ setstate(char *arg_state) if (rand_type == TYPE_0) state[-1] = rand_type; else - state[-1] = MAX_TYPES * (uint32_t)(rptr - state) + rand_type; + state[-1] = MAX_TYPES * (rptr - state) + rand_type; switch(type) { case TYPE_0: case TYPE_1: @@ -441,7 +447,7 @@ setstate(char *arg_state) fprintf(stderr, "random: state info corrupted; not changed.\n"); } - state = (uint32_t *) (new_state + 1); + state = new_state + 1; if (rand_type != TYPE_0) { rptr = &state[rear]; fptr = &state[(rear + rand_sep) % rand_deg]; diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3 index 1aefef6c0d..e61b8141ba 100644 --- a/lib/libc/stdlib/realpath.3 +++ b/lib/libc/stdlib/realpath.3 @@ -12,10 +12,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -33,7 +29,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)realpath.3 8.2 (Berkeley) 2/16/94 -.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.7.2.3 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.14 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/realpath.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd February 16, 1994 @@ -48,7 +44,7 @@ .In sys/param.h .In stdlib.h .Ft "char *" -.Fn realpath "const char *pathname" "char resolved_path[MAXPATHLEN]" +.Fn realpath "const char *pathname" "char resolved_path[PATH_MAX]" .Sh DESCRIPTION The .Fn realpath @@ -68,7 +64,7 @@ The argument .Em must refer to a buffer capable of storing at least -.Dv MAXPATHLEN +.Dv PATH_MAX characters. .Pp The @@ -100,11 +96,7 @@ The function may fail and set the external variable .Va errno for any of the errors specified for the library functions -.Xr chdir 2 , -.Xr close 2 , -.Xr fchdir 2 , .Xr lstat 2 , -.Xr open 2 , .Xr readlink 2 and .Xr getcwd 3 . @@ -125,5 +117,5 @@ when given a relative .Sh HISTORY The .Fn realpath -function call first appeared in +function first appeared in .Bx 4.4 . diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c index d556e0e1d3..3b89c8057d 100644 --- a/lib/libc/stdlib/realpath.c +++ b/lib/libc/stdlib/realpath.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * @(#)realpath.c 8.1 (Berkeley) 2/16/94 - * $FreeBSD: src/lib/libc/stdlib/realpath.c,v 1.9.2.2 2003/06/02 13:31:16 fjoe Exp $ + * $FreeBSD: src/lib/libc/stdlib/realpath.c,v 1.20 2003/05/28 08:23:01 fjoe Exp $ * $DragonFly: src/lib/libc/stdlib/realpath.c,v 1.4 2005/04/28 13:47:15 joerg Exp $ */ diff --git a/lib/libc/stdlib/remque.c b/lib/libc/stdlib/remque.c new file mode 100644 index 0000000000..6da9e397d9 --- /dev/null +++ b/lib/libc/stdlib/remque.c @@ -0,0 +1,30 @@ +/* + * Initial implementation: + * Copyright (c) 2002 Robert Drehmel + * All rights reserved. + * + * As long as the above copyright statement and this notice remain + * unchanged, you can do what ever you want with this file. + * + * $FreeBSD: src/lib/libc/stdlib/remque.c,v 1.3 2003/01/04 07:34:41 tjr Exp $ + */ + +#define _SEARCH_PRIVATE +#include +#include /* for NULL */ + +void +remque(void *element) +{ + struct que_elem *prev, *next, *elem; + + elem = (struct que_elem *)element; + + prev = elem->prev; + next = elem->next; + + if (prev != NULL) + prev->next = next; + if (next != NULL) + next->prev = prev; +} diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c deleted file mode 100644 index 867dab2935..0000000000 --- a/lib/libc/stdlib/setenv.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)setenv.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.5.2.1 2000/09/20 19:46:03 brian Exp $ - * $DragonFly: src/lib/libc/stdlib/setenv.c,v 1.5 2005/04/28 13:51:55 joerg Exp $ - */ - -#include -#include -#include - -extern char **environ; - -char *__findenv (const char *, size_t *); - -/* - * setenv -- - * Set the value of the environmental variable "name" to be - * "value". If rewrite is set, replace any current value. - */ -int -setenv(const char *name, const char *value, int rewrite) -{ - static char **alloced; /* if allocated space before */ - char *c; - size_t l_value, offset; - - if (*value == '=') /* no `=' in value */ - ++value; - l_value = strlen(value); - if ((c = __findenv(name, &offset))) { /* find if already exists */ - if (!rewrite) - return (0); - if (strlen(c) >= l_value) { /* old larger; copy over */ - while ( (*c++ = *value++) ); - return (0); - } - } else { /* create new slot */ - int cnt; - char **p; - - for (p = environ, cnt = 0; *p; ++p, ++cnt); - if (alloced == environ) { - /* just increase size */ - p = realloc(environ, sizeof(char *) * (cnt + 2)); - if (p == NULL) - return (-1); - alloced = environ = p; - } - else { /* get new space */ - /* copy old entries into it */ - p = malloc(sizeof(char *) * (cnt + 2)); - if (p == NULL) - return (-1); - bcopy(environ, p, cnt * sizeof(char *)); - alloced = environ = p; - } - environ[cnt + 1] = NULL; - offset = cnt; - } - for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ - if (!(environ[offset] = /* name + `=' + value */ - malloc((size_t)((int)(c - name) + l_value + 2)))) - return (-1); - for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); - for (*c++ = '='; (*c++ = *value++); ); - return (0); -} - -/* - * unsetenv(name) -- - * Delete environmental variable "name". - */ -void -unsetenv(const char *name) -{ - char **p; - size_t offset; - - while (__findenv(name, &offset)) /* if set multiple times */ - for (p = &environ[offset];; ++p) - if (!(*p = *(p + 1))) - break; -} diff --git a/lib/libc/stdlib/strtol.3 b/lib/libc/stdlib/strtol.3 index dcfe1d0881..1b03705738 100644 --- a/lib/libc/stdlib/strtol.3 +++ b/lib/libc/stdlib/strtol.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)strtol.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.21 2006/05/20 21:11:35 maxim Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.23 2007/04/10 11:17:00 ru Exp $ .\" $DragonFly: src/lib/libc/stdlib/strtol.3,v 1.5 2007/04/10 21:09:00 swildner Exp $ .\" .Dd November 2, 2006 @@ -53,12 +49,12 @@ integer .In stdlib.h .In limits.h .Ft long -.Fn strtol "const char *nptr" "char **endptr" "int base" +.Fn strtol "const char * restrict nptr" "char ** restrict endptr" "int base" .Ft long long -.Fn strtoll "const char *nptr" "char **endptr" "int base" +.Fn strtoll "const char * restrict nptr" "char ** restrict endptr" "int base" .In inttypes.h .Ft intmax_t -.Fn strtoimax "const char *nptr" "char **endptr" "int base" +.Fn strtoimax "const char * restrict nptr" "char ** restrict endptr" "int base" .In sys/types.h .In stdlib.h .In limits.h diff --git a/lib/libc/stdlib/strtoq.c b/lib/libc/stdlib/strtoq.c index 9fa5e2a626..8e09575dbb 100644 --- a/lib/libc/stdlib/strtoq.c +++ b/lib/libc/stdlib/strtoq.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,7 +27,7 @@ * SUCH DAMAGE. * * @(#)strtoq.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.4.6.1 2001/03/02 09:45:20 obrien Exp $ + * $FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.12 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/strtoq.c,v 1.3 2005/11/20 12:37:49 swildner Exp $ */ @@ -41,9 +37,6 @@ /* * Convert a string to a quad integer. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. */ quad_t strtoq(const char *nptr, char **endptr, int base) diff --git a/lib/libc/stdlib/strtoul.3 b/lib/libc/stdlib/strtoul.3 index 451e21c6ee..7de5498256 100644 --- a/lib/libc/stdlib/strtoul.3 +++ b/lib/libc/stdlib/strtoul.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.22 2006/05/20 21:11:35 maxim Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.23 2007/01/09 00:28:10 imp Exp $ .\" $DragonFly: src/lib/libc/stdlib/strtoul.3,v 1.4 2006/11/02 19:48:55 swildner Exp $ .\" .Dd November 2, 2006 @@ -43,6 +39,7 @@ .Sh NAME .Nm strtoul , .Nm strtoull , +.Nm strtoumax , .Nm strtouq .Nd "convert a string to an" .Vt "unsigned long" , "unsigned long long" , uintmax_t , @@ -55,12 +52,12 @@ integer .In stdlib.h .In limits.h .Ft "unsigned long" -.Fn strtoul "const char *nptr" "char **endptr" "int base" +.Fn strtoul "const char * restrict nptr" "char ** restrict endptr" "int base" .Ft "unsigned long long" -.Fn strtoull "const char *nptr" "char **endptr" "int base" +.Fn strtoull "const char * restrict nptr" "char ** restrict endptr" "int base" .In inttypes.h .Ft uintmax_t -.Fn strtoumax "const char *nptr" "char **endptr" "int base" +.Fn strtoumax "const char * restrict nptr" "char ** restrict endptr" "int base" .In sys/types.h .In stdlib.h .In limits.h diff --git a/lib/libc/stdlib/strtouq.c b/lib/libc/stdlib/strtouq.c index 76590cc364..bfb2f50f1e 100644 --- a/lib/libc/stdlib/strtouq.c +++ b/lib/libc/stdlib/strtouq.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,7 +27,7 @@ * SUCH DAMAGE. * * @(#)strtouq.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.4.8.1 2001/03/02 09:45:20 obrien Exp $ + * $FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.12 2007/01/09 00:28:10 imp Exp $ * $DragonFly: src/lib/libc/stdlib/strtouq.c,v 1.3 2005/11/20 12:37:49 swildner Exp $ */ @@ -41,9 +37,6 @@ /* * Convert a string to an unsigned quad integer. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. */ u_quad_t strtouq(const char *nptr, char **endptr, int base) diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3 index 5f0f6fa7d3..89dee4f005 100644 --- a/lib/libc/stdlib/system.3 +++ b/lib/libc/stdlib/system.3 @@ -13,10 +13,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -34,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)system.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.6.2.4 2001/12/14 18:33:58 ru Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.13 2008/06/26 08:24:59 danger Exp $ .\" $DragonFly: src/lib/libc/stdlib/system.3,v 1.2 2003/06/17 04:26:46 dillon Exp $ .\" .Dd June 4, 1993 @@ -75,7 +71,7 @@ pointer, will return non-zero if the command interpreter .Xr sh 1 is available, and zero if it is not. -.Pp +.Sh RETURN VALUES The .Fn system function @@ -98,7 +94,7 @@ The .Fn system function conforms to -.St -isoC . +.St -isoC and is expected to be .St -p1003.2 compatible. diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c index d69c65022d..cff8da8db4 100644 --- a/lib/libc/stdlib/system.c +++ b/lib/libc/stdlib/system.c @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -30,10 +26,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/stdlib/system.c,v 1.5.2.2 2001/10/10 12:50:22 alfred Exp $ - * $DragonFly: src/lib/libc/stdlib/system.c,v 1.5 2005/11/20 12:37:49 swildner Exp $ - * * @(#)system.c 8.1 (Berkeley) 6/4/93 + * $FreeBSD: src/lib/libc/stdlib/system.c,v 1.11 2007/01/09 00:28:10 imp Exp $ + * $DragonFly: src/lib/libc/stdlib/system.c,v 1.5 2005/11/20 12:37:49 swildner Exp $ */ #include "namespace.h" @@ -48,8 +43,6 @@ #include "un-namespace.h" #include "libc_private.h" -int __system(const char *); - int __system(const char *command) { diff --git a/lib/libc/stdlib/tdelete.c b/lib/libc/stdlib/tdelete.c index 7e83d309e2..5597d46f0c 100644 --- a/lib/libc/stdlib/tdelete.c +++ b/lib/libc/stdlib/tdelete.c @@ -9,32 +9,29 @@ * Totally public domain. * * $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ - * $FreeBSD: src/lib/libc/stdlib/tdelete.c,v 1.1.2.1 2000/08/17 07:38:39 jhb Exp $ + * $FreeBSD: src/lib/libc/stdlib/tdelete.c,v 1.6 2003/01/05 02:43:18 tjr Exp $ * $DragonFly: src/lib/libc/stdlib/tdelete.c,v 1.5 2005/11/24 17:18:30 swildner Exp $ */ -#include - -#include #define _SEARCH_PRIVATE #include #include -/* +/* * delete node with given key * - * Parameters: - * vkey: key to be deleted - * vrootp: address of the root of tree -*/ + * vkey: key to be deleted + * vrootp: address of the root of the tree + * compar: function to carry out node comparisons + */ void * -tdelete(const void *vkey, void **vrootp, +tdelete(const void * __restrict vkey, void ** __restrict vrootp, int (*compar)(const void *, const void *)) { node_t **rootp = (node_t **)vrootp; node_t *p, *q, *r; - int cmp; + int cmp; if (rootp == NULL || (p = *rootp) == NULL) return NULL; diff --git a/lib/libc/stdlib/tfind.c b/lib/libc/stdlib/tfind.c index 462cd9ad5a..21cb5eb46f 100644 --- a/lib/libc/stdlib/tfind.c +++ b/lib/libc/stdlib/tfind.c @@ -9,18 +9,15 @@ * Totally public domain. * * $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ - * $FreeBSD: src/lib/libc/stdlib/tfind.c,v 1.1.2.1 2000/08/17 07:38:39 jhb Exp $ - * $DragonFly: src/lib/libc/stdlib/tfind.c,v 1.5 2005/11/24 17:18:30 swildner Exp $ + * $FreeBSD: src/lib/libc/stdlib/tfind.c,v 1.5 2003/01/05 02:43:18 tjr Exp $ + * $DragonFly: src/lib/libc/stdlib/tsearch.c,v 1.6 2005/11/24 17:18:30 swildner Exp $ */ -#include - -#include #define _SEARCH_PRIVATE #include #include -/* +/* * find a node, or return 0 * * Parameters: @@ -28,7 +25,7 @@ * vrootp: address of the tree root */ void * -tfind(const void *vkey, void **vrootp, +tfind(const void *vkey, void * const *vrootp, int (*compar)(const void *, const void *)) { node_t **rootp = (node_t **)vrootp; diff --git a/lib/libc/stdlib/tsearch.3 b/lib/libc/stdlib/tsearch.3 index a42e3809bd..082acf042a 100644 --- a/lib/libc/stdlib/tsearch.3 +++ b/lib/libc/stdlib/tsearch.3 @@ -25,8 +25,8 @@ .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp -.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.1.2.6 2001/12/14 18:33:58 ru Exp $ -.\" $DragonFly: src/lib/libc/stdlib/tsearch.3,v 1.5 2007/08/18 20:48:47 swildner Exp $ +.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.15 2006/06/23 13:36:33 keramida Exp $ +.\" $DragonFly: src/lib/libc/stdlib/tsearch.c,v 1.6 2005/11/24 17:18:30 swildner Exp $ .\" .Dd June 15, 1997 .Dt TSEARCH 3 @@ -42,13 +42,13 @@ .Sh SYNOPSIS .In search.h .Ft void * -.Fn tdelete "const void *key" "void **rootp" "int (*compar) (const void *, const void *)" +.Fn tdelete "const void * restrict key" "void ** restrict rootp" "int (*compar) (const void *, const void *)" .Ft void * -.Fn tfind "const void *key" "void **rootp" "int (*compar) (const void *, const void *)" +.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)" .Ft void * .Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)" .Ft void -.Fn twalk "const void *root" "void (*compar) (const void *, VISIT, int)" +.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)" .Sh DESCRIPTION The .Fn tdelete , @@ -57,11 +57,14 @@ The and .Fn twalk functions manage binary search trees based on algorithms T and D -from Knuth (6.2.2). The comparison function passed in by +from Knuth (6.2.2). +The comparison function passed in by the user has the same style of return values as .Xr strcmp 3 . .Pp -.Fn Tfind +The +.Fn tfind +function searches for the datum matched by the argument .Fa key in the binary tree rooted at @@ -69,16 +72,21 @@ in the binary tree rooted at returning a pointer to the datum if it is found and NULL if it is not. .Pp -.Fn Tsearch +The +.Fn tsearch +function is identical to .Fn tfind except that if no match is found, .Fa key -is inserted into the tree and a pointer to it is returned. If +is inserted into the tree and a pointer to it is returned. +If .Fa rootp points to a NULL value a new binary search tree is created. .Pp -.Fn Tdelete +The +.Fn tdelete +function deletes a node from the specified binary search tree and returns a pointer to the parent of the node to be deleted. It takes the same arguments as @@ -89,13 +97,17 @@ If the node to be deleted is the root of the binary search tree, .Fa rootp will be adjusted. .Pp -.Fn Twalk +The +.Fn twalk +function walks the binary search tree rooted in .Fa root and calls the function .Fa action on each node. -.Fa Action +The +.Fa action +function is called with three arguments: a pointer to the current node, a value from the enum .Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;" @@ -107,10 +119,12 @@ The function returns NULL if allocation of a new node fails (usually due to a lack of free memory). .Pp -.Fn Tfind , +The +.Fn tfind , .Fn tsearch , and .Fn tdelete +functions return NULL if .Fa rootp is NULL or the datum cannot be found. diff --git a/lib/libc/stdlib/tsearch.c b/lib/libc/stdlib/tsearch.c index 9479b4fd27..ffefef9f5b 100644 --- a/lib/libc/stdlib/tsearch.c +++ b/lib/libc/stdlib/tsearch.c @@ -9,23 +9,22 @@ * Totally public domain. * * $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ - * $FreeBSD: src/lib/libc/stdlib/tsearch.c,v 1.1.2.1 2000/08/17 07:38:39 jhb Exp $ + * $FreeBSD: src/lib/libc/stdlib/tsearch.c,v 1.4 2003/01/05 02:43:18 tjr Exp $ * $DragonFly: src/lib/libc/stdlib/tsearch.c,v 1.6 2005/11/24 17:18:30 swildner Exp $ */ -#include - -#include #define _SEARCH_PRIVATE #include #include -/* find or insert datum into search tree +/* + * find or insert datum into search tree * * Parameters: * vkey: key to be located * vrootp: address of tree root */ + void * tsearch(const void *vkey, void **vrootp, int (*compar)(const void *, const void *)) diff --git a/lib/libc/stdlib/twalk.c b/lib/libc/stdlib/twalk.c index c12b600dc3..cb480180c0 100644 --- a/lib/libc/stdlib/twalk.c +++ b/lib/libc/stdlib/twalk.c @@ -9,21 +9,19 @@ * Totally public domain. * * $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $ - * $FreeBSD: src/lib/libc/stdlib/twalk.c,v 1.1.2.1 2000/08/17 07:38:39 jhb Exp $ + * $FreeBSD: src/lib/libc/stdlib/twalk.c,v 1.5 2003/01/05 02:43:18 tjr Exp $ * $DragonFly: src/lib/libc/stdlib/twalk.c,v 1.5 2005/11/24 17:18:30 swildner Exp $ */ -#include - -#include #define _SEARCH_PRIVATE #include #include -static void trecurse (const node_t *, - void (*action)(const void *, VISIT, int), int level); +static void trecurse(const node_t *, + void (*action)(const void *, VISIT, int), int level); -/* Walk the nodes of a tree +/* + * Walk the nodes of a tree * * Parameters: * root: Root of the tree to be walked @@ -46,7 +44,8 @@ trecurse(const node_t *root, void (*action)(const void *, VISIT, int), } } -/* Walk the nodes of a tree +/* + * Walk the nodes of a tree * * Parameters: * vroot: Root of the tree to be walked diff --git a/libexec/pppoed/pppoed.c b/libexec/pppoed/pppoed.c index d21e58d870..de8304f3c9 100644 --- a/libexec/pppoed/pppoed.c +++ b/libexec/pppoed/pppoed.c @@ -260,7 +260,7 @@ Spawn(const char *prog __unused, const char *acname, const char *provider, struct ng_mesg *rep = (struct ng_mesg *)msgbuf; struct ngpppoe_sts *sts = (struct ngpppoe_sts *)(msgbuf + sizeof *rep); struct ngpppoe_init_data *data; - char env[sizeof(HISMACADDR)+18], unknown[14], sessionid[5], *path; + char env[18], unknown[14], sessionid[5], *path; unsigned char *macaddr; const char *msg; int ret, slen; @@ -354,11 +354,11 @@ Spawn(const char *prog __unused, const char *acname, const char *provider, /* Put the peer's MAC address in the environment */ if (sz >= sizeof(struct ether_header)) { macaddr = ((struct ether_header *)request)->ether_shost; - snprintf(env, sizeof(env), "%s=%x:%x:%x:%x:%x:%x", HISMACADDR, + snprintf(env, sizeof(env), "%x:%x:%x:%x:%x:%x", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); - if (putenv(env) != 0) - syslog(LOG_INFO, "putenv: cannot set %s: %m", env); + if (setenv(HISMACADDR, env, 1) != 0) + syslog(LOG_INFO, "setenv: cannot set %s: %m", HISMACADDR); } /* And send our request data to the waiting node */ diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c index 151fa3524e..860cf0588d 100644 --- a/usr.bin/du/du.c +++ b/usr.bin/du/du.c @@ -131,14 +131,14 @@ main(int argc, char **argv) cflag = 1; break; case 'h': - if (putenv("BLOCKSIZE=512") == -1) - warn("putenv: cannot set BLOCKSIZE=512"); + if (setenv("BLOCKSIZE", "512", 1) == -1) + warn("setenv: cannot set BLOCKSIZE=512"); hflag = 1; break; case 'k': hflag = 0; - if (putenv("BLOCKSIZE=1024") == -1) - warn("putenv: cannot set BLOCKSIZE=1024"); + if (setenv("BLOCKSIZE", "1024", 1) == -1) + warn("setenv: cannot set BLOCKSIZE=1024"); break; case 'r': /* Compatibility. */ break; diff --git a/usr.bin/env/env.c b/usr.bin/env/env.c index 468649bd50..8b59033969 100644 --- a/usr.bin/env/env.c +++ b/usr.bin/env/env.c @@ -65,8 +65,10 @@ main(int argc, char **argv) usage(); } for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) { - if (setenv(*argv, ++p, 1) == -1) - err(1, "setenv: cannot set %s=%s", *argv, p); + *p = '\0'; + if (setenv(*argv, p + 1, 1) == -1) + err(1, "setenv: cannot set %s=%s", *argv, p + 1); + *p = '='; } if (*argv) { diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c index 6b5f45535d..0de352a656 100644 --- a/usr.bin/limits/limits.c +++ b/usr.bin/limits/limits.c @@ -434,8 +434,10 @@ main(int argc, char *argv[]) /* set leading environment variables, like eval(1) */ while (*argv && (p = strchr(*argv, '='))) { - if (setenv(*argv++, ++p, 1) == -1) - err(1, "setenv: cannot set %s=%s", *argv, p); + *p = '\0'; + if (setenv(*argv++, p + 1, 1) == -1) + err(1, "setenv: cannot set %s=%s", *argv, p + 1); + *p = '='; } /* Set limits */ diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c index 1438b95b4a..c2fe784123 100644 --- a/usr.sbin/pstat/pstat.c +++ b/usr.sbin/pstat/pstat.c @@ -226,8 +226,8 @@ main(int argc, char **argv) fileflag = 1; break; case 'k': - if (putenv("BLOCKSIZE=1K") == -1) - warn("putenv: cannot set BLOCKSIZE=1K"); + if (setenv("BLOCKSIZE", "1K", 1) == -1) + warn("setenv: cannot set BLOCKSIZE=1K"); break; case 'M': memf = optarg; -- 2.11.4.GIT