summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib')
-rw-r--r--src/lib/libc/stdlib/Makefile.inc56
-rw-r--r--src/lib/libc/stdlib/_rand48.c4
-rw-r--r--src/lib/libc/stdlib/a64l.3144
-rw-r--r--src/lib/libc/stdlib/a64l.c28
-rw-r--r--src/lib/libc/stdlib/abort.320
-rw-r--r--src/lib/libc/stdlib/abort.c25
-rw-r--r--src/lib/libc/stdlib/abs.317
-rw-r--r--src/lib/libc/stdlib/abs.c3
-rw-r--r--src/lib/libc/stdlib/alloca.335
-rw-r--r--src/lib/libc/stdlib/atexit.313
-rw-r--r--src/lib/libc/stdlib/atexit.c141
-rw-r--r--src/lib/libc/stdlib/atexit.h57
-rw-r--r--src/lib/libc/stdlib/atof.37
-rw-r--r--src/lib/libc/stdlib/atof.c3
-rw-r--r--src/lib/libc/stdlib/atoi.326
-rw-r--r--src/lib/libc/stdlib/atoi.c3
-rw-r--r--src/lib/libc/stdlib/atol.313
-rw-r--r--src/lib/libc/stdlib/atol.c3
-rw-r--r--src/lib/libc/stdlib/atoll.3 (renamed from src/lib/libc/stdlib/calloc.3)53
-rw-r--r--src/lib/libc/stdlib/atoll.c45
-rw-r--r--src/lib/libc/stdlib/bsearch.319
-rw-r--r--src/lib/libc/stdlib/bsearch.c5
-rw-r--r--src/lib/libc/stdlib/calloc.c14
-rw-r--r--src/lib/libc/stdlib/cfree.c49
-rw-r--r--src/lib/libc/stdlib/div.317
-rw-r--r--src/lib/libc/stdlib/div.c3
-rw-r--r--src/lib/libc/stdlib/drand48.c4
-rw-r--r--src/lib/libc/stdlib/ecvt.3172
-rw-r--r--src/lib/libc/stdlib/ecvt.c110
-rw-r--r--src/lib/libc/stdlib/erand48.c4
-rw-r--r--src/lib/libc/stdlib/exit.325
-rw-r--r--src/lib/libc/stdlib/exit.c36
-rw-r--r--src/lib/libc/stdlib/free.382
-rw-r--r--src/lib/libc/stdlib/gcvt.c106
-rw-r--r--src/lib/libc/stdlib/getenv.366
-rw-r--r--src/lib/libc/stdlib/getenv.c66
-rw-r--r--src/lib/libc/stdlib/getopt.3167
-rw-r--r--src/lib/libc/stdlib/getopt.c6
-rw-r--r--src/lib/libc/stdlib/getopt_long.3373
-rw-r--r--src/lib/libc/stdlib/getopt_long.c543
-rw-r--r--src/lib/libc/stdlib/getsubopt.3147
-rw-r--r--src/lib/libc/stdlib/getsubopt.c106
-rw-r--r--src/lib/libc/stdlib/heapsort.c5
-rw-r--r--src/lib/libc/stdlib/insque.3100
-rw-r--r--src/lib/libc/stdlib/insque.c52
-rw-r--r--src/lib/libc/stdlib/jrand48.c4
-rw-r--r--src/lib/libc/stdlib/l64a.c15
-rw-r--r--src/lib/libc/stdlib/labs.313
-rw-r--r--src/lib/libc/stdlib/labs.c3
-rw-r--r--src/lib/libc/stdlib/lcong48.c4
-rw-r--r--src/lib/libc/stdlib/ldiv.323
-rw-r--r--src/lib/libc/stdlib/ldiv.c3
-rw-r--r--src/lib/libc/stdlib/lrand48.c4
-rw-r--r--src/lib/libc/stdlib/lsearch.3 (renamed from src/lib/libc/stdlib/realloc.3)127
-rw-r--r--src/lib/libc/stdlib/lsearch.c90
-rw-r--r--src/lib/libc/stdlib/malloc.3376
-rw-r--r--src/lib/libc/stdlib/malloc.c1574
-rw-r--r--src/lib/libc/stdlib/memory.314
-rw-r--r--src/lib/libc/stdlib/merge.c17
-rw-r--r--src/lib/libc/stdlib/mrand48.c4
-rw-r--r--src/lib/libc/stdlib/multibyte.c9
-rw-r--r--src/lib/libc/stdlib/nrand48.c4
-rw-r--r--src/lib/libc/stdlib/putenv.c19
-rw-r--r--src/lib/libc/stdlib/qabs.312
-rw-r--r--src/lib/libc/stdlib/qabs.c3
-rw-r--r--src/lib/libc/stdlib/qdiv.316
-rw-r--r--src/lib/libc/stdlib/qdiv.c3
-rw-r--r--src/lib/libc/stdlib/qsort.357
-rw-r--r--src/lib/libc/stdlib/qsort.c34
-rw-r--r--src/lib/libc/stdlib/radixsort.333
-rw-r--r--src/lib/libc/stdlib/radixsort.c15
-rw-r--r--src/lib/libc/stdlib/rand.329
-rw-r--r--src/lib/libc/stdlib/rand.c18
-rw-r--r--src/lib/libc/stdlib/rand48.343
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3107
-rw-r--r--src/lib/libc/stdlib/random.c142
-rw-r--r--src/lib/libc/stdlib/realpath.320
-rw-r--r--src/lib/libc/stdlib/realpath.c27
-rw-r--r--src/lib/libc/stdlib/remque.c48
-rw-r--r--src/lib/libc/stdlib/seed48.c4
-rw-r--r--src/lib/libc/stdlib/setenv.c16
-rw-r--r--src/lib/libc/stdlib/srand48.c4
-rw-r--r--src/lib/libc/stdlib/strtod.337
-rw-r--r--src/lib/libc/stdlib/strtod.c253
-rw-r--r--src/lib/libc/stdlib/strtol.3142
-rw-r--r--src/lib/libc/stdlib/strtol.c70
-rw-r--r--src/lib/libc/stdlib/strtoll.c (renamed from src/lib/libc/stdlib/strtoq.c)90
-rw-r--r--src/lib/libc/stdlib/strtoul.3141
-rw-r--r--src/lib/libc/stdlib/strtoul.c44
-rw-r--r--src/lib/libc/stdlib/strtoull.c (renamed from src/lib/libc/stdlib/strtouq.c)62
-rw-r--r--src/lib/libc/stdlib/system.344
-rw-r--r--src/lib/libc/stdlib/system.c23
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3127
-rw-r--r--src/lib/libc/stdlib/tsearch.c126
96 files changed, 5590 insertions, 1521 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 782a4ab022..bfbbdcb7f4 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -1,24 +1,28 @@
1# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91 1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $
2# $Id: Makefile.inc,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
3 2
4# stdlib sources 3# stdlib sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
6 5
7SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \ 6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
8 exit.c getenv.c getopt.c heapsort.c l64a.c malloc.c merge.c \ 7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt.c getopt_long.c \
8 getsubopt.c heapsort.c l64a.c lsearch.c malloc.c merge.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \
10 setenv.c strtod.c strtol.c strtoq.c strtoul.c strtouq.c system.c \ 10 setenv.c strtod.c strtol.c strtoll.c strtoul.c strtoull.c system.c \
11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \ 11 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
12 mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c 12 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c
13 13
14.if (${MACHINE_ARCH} == "m68k") 14.if (${MACHINE_ARCH} == "m68k")
15SRCS+= abs.S div.c labs.c ldiv.c 15SRCS+= abs.S div.c labs.c ldiv.c
16LSRCS+= abs.c
16.elif (${MACHINE_ARCH} == "i386") 17.elif (${MACHINE_ARCH} == "i386")
17SRCS+= abs.S div.S labs.S ldiv.S 18SRCS+= abs.S div.S labs.S ldiv.S
19LSRCS+= abs.c div.c labs.c ldiv.c
18.elif (${MACHINE_ARCH} == "ns32k") 20.elif (${MACHINE_ARCH} == "ns32k")
19SRCS+= abs.S div.c labs.c ldiv.c 21SRCS+= abs.S div.c labs.c ldiv.c
22LSRCS+= abs.c
20.elif (${MACHINE_ARCH} == "tahoe") 23.elif (${MACHINE_ARCH} == "tahoe")
21SRCS+= abs.S div.c labs.c ldiv.c 24SRCS+= abs.S div.c labs.c ldiv.c
25LSRCS+= abs.c
22.elif (${MACHINE_ARCH} == "vax") 26.elif (${MACHINE_ARCH} == "vax")
23SRCS+= abs.c div.c labs.c ldiv.c 27SRCS+= abs.c div.c labs.c ldiv.c
24.elif (${MACHINE_ARCH} == "alpha") 28.elif (${MACHINE_ARCH} == "alpha")
@@ -28,18 +32,36 @@ SRCS+= abs.c div.c labs.c ldiv.c
28SRCS+= abs.c div.c labs.c ldiv.c 32SRCS+= abs.c div.c labs.c ldiv.c
29.endif 33.endif
30 34
31MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ 35.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 36SRCS+= insque.S remque.S
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 37.else
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 38SRCS+= insque.c remque.c
35 system.3 39.endif
40
41MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
42 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
43 getsubopt.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 memory.3 qabs.3 \
44 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
45 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
36 46
47MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 48MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
49MLINKS+=getopt_long.3 getopt_long_only.3
50MLINKS+=insque.3 remque.3
51MLINKS+=lsearch.3 lfind.3
52MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
53MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 54MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 55MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 56MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 57MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 58MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 59MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
44MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 60MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
45MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3 61MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
62MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
63MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
64MLINKS+=tsearch.3 tfind.3
65MLINKS+=tsearch.3 tdelete.3
66MLINKS+=tsearch.3 twalk.3
67MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
index 83ade4645a..fed7372f68 100644
--- a/src/lib/libc/stdlib/_rand48.c
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: _rand48.c,v 1.2 1996/08/19 08:33:19 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16unsigned short __rand48_seed[3] = { 20unsigned short __rand48_seed[3] = {
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..6b9fd23154
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,144 @@
1.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. The name of the author may not be used to endorse or promote products
13.\" derived from this software without specific prior written permission.
14.\"
15.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.\"
26.\" $OpenBSD: a64l.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
27.\"
28.Dd August 17, 1997
29.Dt A64L 3
30.Os
31.Sh NAME
32.Nm a64l ,
33.Nm l64a
34.Nd convert between 32-bit integer and radix-64 ASCII string
35.Sh SYNOPSIS
36.Fd #include <stdlib.h>
37.Ft long
38.Fn a64l "const char *s"
39.Ft char *
40.Fn l64a "long l"
41.Sh DESCRIPTION
42The
43.Fn a64l
44and
45.Fn l64a
46functions are used to maintain numbers stored in radix-64
47.Tn ASCII
48characters.
49This is a notation by which 32-bit integers
50can be represented by up to six characters; each character represents a
51.Dq digit
52in a radix-64 notation.
53.Pp
54The characters used to represent digits are
55.Ql \&.
56for 0,
57.Ql /
58for 1,
59.Ql 0
60through
61.Ql 9
62for 2-11,
63.Ql A
64through
65.Ql Z
66for 12-37, and
67.Ql a
68through
69.Ql z
70for 38-63.
71.Pp
72The
73.Fn a64l
74function takes a pointer to a null-terminated radix-64 representation
75and returns a corresponding 32-bit value.
76If the string pointed to by
77.Fa s
78contains more than six characters,
79.Fn a64l
80will use the first six.
81.Fn a64l
82scans the character string from left to right, decoding
83each character as a 6-bit radix-64 number.
84If a long integer is
85larger than 32 bits, the return value will be sign-extended.
86.Pp
87.Fn l64a
88takes a long integer argument
89.Fa l
90and returns a pointer to the corresponding radix-64 representation.
91.Sh RETURN VALUES
92On success,
93.Fn a64l
94returns a 32-bit representation of
95.Fa s .
96If
97.Fa s
98is a null pointer or if it contains digits other than those described above,
99.Fn a64l
100returns \-1 and sets the global variable
101.Va errno
102to
103.Er EINVAL .
104.Pp
105On success,
106.Fn l64a
107returns a pointer to a string containing the radix-64 representation of
108.Fa l .
109If
110.Fa l
111is 0,
112.Fn l64a
113returns a pointer to the empty string.
114If
115.Fa l
116is negative,
117.Fn l64a
118returns a null pointer and sets the global variable
119.Va errno
120to
121.Er EINVAL .
122.Sh WARNINGS
123The value returned by
124.Fn l64a
125is a pointer into a static buffer, the contents of which
126will be overwritten by subsequent calls.
127.Pp
128The value returned by
129.Fn a64l
130may be incorrect if the value is too large; for that reason, only strings
131that resulted from a call to
132.Fn l64a
133should be used to call
134.Fn a64l .
135.Pp
136If a long integer is larger than 32 bits, only the low-order
13732 bits are used.
138.Sh STANDARDS
139The
140.Fn a64l
141and
142.Fn l64a
143functions conform to
144.St -xpg4.2 .
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
index 03fc77e034..a68f0a6dcd 100644
--- a/src/lib/libc/stdlib/a64l.c
+++ b/src/lib/libc/stdlib/a64l.c
@@ -4,8 +4,11 @@
4 */ 4 */
5 5
6#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$NetBSD: a64l.c,v 1.3 1995/05/11 23:04:47 jtc Exp $"; 7static char *rcsid = "$OpenBSD: a64l.c,v 1.3 1997/08/17 22:58:34 millert Exp $";
8#endif 8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
9 12
10long 13long
11a64l(s) 14a64l(s)
@@ -14,21 +17,30 @@ a64l(s)
14 long value, digit, shift; 17 long value, digit, shift;
15 int i; 18 int i;
16 19
20 if (s == NULL) {
21 errno = EINVAL;
22 return(-1L);
23 }
24
17 value = 0; 25 value = 0;
18 shift = 0; 26 shift = 0;
19 for (i = 0; *s && i < 6; i++, s++) { 27 for (i = 0; *s && i < 6; i++, s++) {
20 if (*s <= '/') 28 if (*s >= '.' && *s <= '/')
21 digit = *s - '.'; 29 digit = *s - '.';
22 else if (*s <= '9') 30 else if (*s >= '0' && *s <= '9')
23 digit = *s - '0' + 2; 31 digit = *s - '0' + 2;
24 else if (*s <= 'Z') 32 else if (*s >= 'A' && *s <= 'Z')
25 digit = *s - 'A' + 12; 33 digit = *s - 'A' + 12;
26 else 34 else if (*s >= 'a' && *s <= 'z')
27 digit = *s - 'a' + 38; 35 digit = *s - 'a' + 38;
36 else {
37 errno = EINVAL;
38 return(-1L);
39 }
28 40
29 value |= digit << shift; 41 value |= digit << shift;
30 shift += 6; 42 shift += 6;
31 } 43 }
32 44
33 return (long) value; 45 return(value);
34} 46}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
index ab57327585..743d42dd8a 100644
--- a/src/lib/libc/stdlib/abort.3
+++ b/src/lib/libc/stdlib/abort.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)abort.3 6.7 (Berkeley) 6/29/91 36.\" $OpenBSD: abort.3,v 1.6 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: abort.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ABORT 3 39.Dt ABORT 3
@@ -49,23 +48,20 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn abort 50.Fn abort
52function causes abnormal program termination to occur, unless the 51function causes abnormal program termination to occur, unless the signal
53signal
54.Dv SIGABRT 52.Dv SIGABRT
55is being caught and the signal handler does not return. 53is being caught and the signal handler does not return.
56.Pp 54.Pp
57No open streams are closed or flushed. 55Any open streams are flushed and closed.
58.Sh RETURN VALUES 56.Sh RETURN VALUES
59The 57The
60.Nm abort 58.Fn abort
61function 59function never returns.
62never returns.
63.Sh SEE ALSO 60.Sh SEE ALSO
64.Xr sigaction 2 , 61.Xr sigaction 2 ,
65.Xr exit 2 62.Xr exit 3
66.Sh STANDARDS 63.Sh STANDARDS
67The 64The
68.Fn abort 65.Fn abort
69function 66function conforms to
70conforms to 67.St -p1003.1-90 .
71.St -ansiC .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
index c298e016b4..a833a1a8b7 100644
--- a/src/lib/libc/stdlib/abort.c
+++ b/src/lib/libc/stdlib/abort.c
@@ -32,26 +32,43 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abort.c 5.11 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: abort.c,v 1.11 2002/11/05 22:19:55 marc Exp $";
36static char *rcsid = "$Id: abort.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <signal.h> 38#include <signal.h>
40#include <stdlib.h> 39#include <stdlib.h>
41#include <unistd.h> 40#include <unistd.h>
41#include "thread_private.h"
42#include "atexit.h"
42 43
43void 44void
44abort() 45abort()
45{ 46{
47 struct atexit *p = __atexit;
48 static int cleanup_called = 0;
46 sigset_t mask; 49 sigset_t mask;
47 50
51
48 sigfillset(&mask); 52 sigfillset(&mask);
49 /* 53 /*
50 * don't block SIGABRT to give any handler a chance; we ignore 54 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway. 55 * any errors -- X311J doesn't allow abort to return anyway.
52 */ 56 */
53 sigdelset(&mask, SIGABRT); 57 sigdelset(&mask, SIGABRT);
54 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 58 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
59
60 /*
61 * POSIX requires we flush stdio buffers on abort
62 */
63 if (cleanup_called == 0) {
64 while (p != NULL && p->next != NULL)
65 p = p->next;
66 if (p != NULL && p->fns[0] != NULL) {
67 cleanup_called = 1;
68 (*p->fns[0])();
69 }
70 }
71
55 (void)kill(getpid(), SIGABRT); 72 (void)kill(getpid(), SIGABRT);
56 73
57 /* 74 /*
@@ -59,7 +76,7 @@ abort()
59 * it again, only harder. 76 * it again, only harder.
60 */ 77 */
61 (void)signal(SIGABRT, SIG_DFL); 78 (void)signal(SIGABRT, SIG_DFL);
62 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 79 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
63 (void)kill(getpid(), SIGABRT); 80 (void)kill(getpid(), SIGABRT);
64 exit(1); 81 exit(1);
65} 82}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
index 4748d89e77..0f7c097ade 100644
--- a/src/lib/libc/stdlib/abs.3
+++ b/src/lib/libc/stdlib/abs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)abs.3 6.4 (Berkeley) 6/29/91 36.\" $OpenBSD: abs.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: abs.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ABS 3 39.Dt ABS 3
@@ -49,21 +48,17 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn abs 50.Fn abs
52function 51function computes the absolute value of the integer
53computes 52.Fa j .
54the absolute value of the integer
55.Ar j .
56.Sh RETURN VALUES 53.Sh RETURN VALUES
57The 54The
58.Fn abs 55.Fn abs
59function 56function returns the absolute value.
60returns
61the absolute value.
62.Sh SEE ALSO 57.Sh SEE ALSO
63.Xr floor 3 ,
64.Xr labs 3 ,
65.Xr cabs 3 , 58.Xr cabs 3 ,
59.Xr floor 3 ,
66.Xr hypot 3 , 60.Xr hypot 3 ,
61.Xr labs 3 ,
67.Xr math 3 62.Xr math 3
68.Sh STANDARDS 63.Sh STANDARDS
69The 64The
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
index 64468e0224..7c79e4073c 100644
--- a/src/lib/libc/stdlib/abs.c
+++ b/src/lib/libc/stdlib/abs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: abs.c,v 1.2 1996/08/19 08:33:21 tholo Exp $";
36static char *rcsid = "$Id: abs.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
index dcb97ab11c..431443a6e6 100644
--- a/src/lib/libc/stdlib/alloca.3
+++ b/src/lib/libc/stdlib/alloca.3
@@ -29,12 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)alloca.3 5.1 (Berkeley) 5/2/91 32.\" $OpenBSD: alloca.3,v 1.9 2001/12/06 04:21:27 deraadt Exp $
33.\" $Id: alloca.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd May 2, 1991
36.Dt ALLOCA 3 35.Dt ALLOCA 3
37.Os BSD 4 36.Os
38.Sh NAME 37.Sh NAME
39.Nm alloca 38.Nm alloca
40.Nd memory allocator 39.Nd memory allocator
@@ -45,35 +44,41 @@
45.Sh DESCRIPTION 44.Sh DESCRIPTION
46The 45The
47.Fn alloca 46.Fn alloca
48function 47function allocates
49allocates
50.Fa size 48.Fa size
51bytes of space in the stack frame of the caller. 49bytes of space in the stack frame of the caller.
52This temporary space is automatically freed on 50This temporary space is automatically freed on return.
53return.
54.Sh RETURN VALUES 51.Sh RETURN VALUES
55The 52The
56.Fn alloca 53.Fn alloca
57function returns a pointer to the beginning of the allocated space. 54function returns a pointer to the beginning of the allocated space.
58If the allocation failed, a
59.Dv NULL
60pointer is returned.
61.Sh SEE ALSO 55.Sh SEE ALSO
56.Xr pagesize 1 ,
62.Xr brk 2 , 57.Xr brk 2 ,
63.Xr pagesize 2
64.Xr calloc 3 , 58.Xr calloc 3 ,
65.Xr malloc 3 , 59.Xr malloc 3 ,
66.Xr realloc 3 , 60.Xr realloc 3
67.Sh BUGS 61.Sh BUGS
68The 62The
69.Fn alloca 63.Fn alloca
70function 64function is machine dependent; its use is discouraged.
71is machine dependent; its use is discouraged.
72.\" .Sh HISTORY 65.\" .Sh HISTORY
73.\" The 66.\" The
74.\" .Fn alloca 67.\" .Fn alloca
75.\" function appeared in 68.\" function appeared in
76.\" .Bx ?? . 69.\" .Bx ?? .
77.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd 70.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
78.\" The first man page (or link to a man page that I can find at the 71.\" The first man page (or link to a man page that I can find at the
79.\" moment is 4.3... 72.\" moment is 4.3...
73.Pp
74The
75.Fn alloca
76function is slightly unsafe because it cannot ensure that the pointer
77returned points to a valid and usable block of memory.
78The allocation made may exceed the bounds of the stack, or even go
79further into other objects in memory, and
80.Fn alloca
81cannot determine such an error.
82Avoid
83.Fn alloca
84with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
index 07de054d3c..5d79ede649 100644
--- a/src/lib/libc/stdlib/atexit.3
+++ b/src/lib/libc/stdlib/atexit.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atexit.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atexit.3,v 1.4 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: atexit.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATEXIT 3 39.Dt ATEXIT 3
@@ -49,13 +48,12 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn atexit 50.Fn atexit
52function 51function registers the given
53registers the given 52.Fa function
54.Ar function
55to be called at program exit, whether via 53to be called at program exit, whether via
56.Xr exit 3 54.Xr exit 3
57or via return from the program's 55or via return from the program's
58.Em main . 56.Fn main .
59Functions so registered are called in reverse order; 57Functions so registered are called in reverse order;
60no arguments are passed. 58no arguments are passed.
61At least 32 functions can always be registered, 59At least 32 functions can always be registered,
@@ -73,6 +71,5 @@ The existing list of functions is unmodified.
73.Sh STANDARDS 71.Sh STANDARDS
74The 72The
75.Fn atexit 73.Fn atexit
76function 74function conforms to
77conforms to
78.St -ansiC . 75.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index 4da1eb0d9c..98564d0dd3 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,68 +1,135 @@
1/*- 1/*
2 * Copyright (c) 1990 The Regents of the University of California. 2 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
10 * are met: 7 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 * 8 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 9 * - Redistributions of source code must retain the above copyright
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 * notice, this list of conditions and the following disclaimer.
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 * - Redistributions in binary form must reproduce the above
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 12 * copyright notice, this list of conditions and the following
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 * disclaimer in the documentation and/or other materials provided
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 * with the distribution.
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 *
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 * SUCH DAMAGE. 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
35 */ 29 */
36 30
37#if defined(LIBC_SCCS) && !defined(lint) 31#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)atexit.c 5.2 (Berkeley) 11/14/90";*/ 32static char *rcsid = "$OpenBSD: atexit.c,v 1.7 2002/09/14 22:03:14 dhartmei Exp $";
39static char *rcsid = "$Id: atexit.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 33#endif /* LIBC_SCCS and not lint */
41 34
35#include <sys/types.h>
36#include <sys/mman.h>
42#include <stdlib.h> 37#include <stdlib.h>
38#include <unistd.h>
43#include "atexit.h" 39#include "atexit.h"
44 40
41int __atexit_invalid = 1;
45struct atexit *__atexit; 42struct atexit *__atexit;
46 43
47/* 44/*
45 * Function pointers are stored in a linked list of pages. The list
46 * is initially empty, and pages are allocated on demand. The first
47 * function pointer in the first allocated page (the last one in
48 * the linked list) is reserved for the cleanup function.
49 *
50 * Outside the following two functions, all pages are mprotect()'ed
51 * to prevent unintentional/malicious corruption.
52 *
53 * The free(malloc(1)) is a workaround causing malloc_init() to
54 * ensure that malloc.c gets the first mmap() call for its sbrk()
55 * games.
56 */
57
58/*
48 * Register a function to be performed at exit. 59 * Register a function to be performed at exit.
49 */ 60 */
50int 61int
51atexit(fn) 62atexit(fn)
52 void (*fn)(); 63 void (*fn)();
53{ 64{
54 static struct atexit __atexit0; /* one guaranteed table */ 65 register struct atexit *p = __atexit;
55 register struct atexit *p; 66 register int pgsize = getpagesize();
56 67
57 if ((p = __atexit) == NULL) 68 if (pgsize < sizeof(*p))
58 __atexit = p = &__atexit0; 69 return (-1);
59 else if (p->ind >= ATEXIT_SIZE) { 70 if (p != NULL) {
60 if ((p = malloc(sizeof(*p))) == NULL) 71 if (p->ind + 1 >= p->max)
72 p = NULL;
73 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
74 return (-1);
75 }
76 if (p == NULL) {
77 if (__atexit_invalid) {
78 free(malloc(1));
79 __atexit_invalid = 0;
80 }
81 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
82 MAP_ANON | MAP_PRIVATE, -1, 0);
83 if (p == MAP_FAILED)
61 return (-1); 84 return (-1);
62 p->ind = 0; 85 if (__atexit == NULL) {
86 p->fns[0] = NULL;
87 p->ind = 1;
88 } else
89 p->ind = 0;
90 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
91 sizeof(p->fns[0]);
63 p->next = __atexit; 92 p->next = __atexit;
64 __atexit = p; 93 __atexit = p;
65 } 94 }
66 p->fns[p->ind++] = fn; 95 p->fns[p->ind++] = fn;
96 if (mprotect(p, pgsize, PROT_READ))
97 return (-1);
67 return (0); 98 return (0);
68} 99}
100
101/*
102 * Register the cleanup function
103 */
104void
105__atexit_register_cleanup(fn)
106 void (*fn)();
107{
108 register struct atexit *p = __atexit;
109 register int pgsize = getpagesize();
110
111 if (pgsize < sizeof(*p))
112 return;
113 while (p != NULL && p->next != NULL)
114 p = p->next;
115 if (p == NULL) {
116 if (__atexit_invalid) {
117 free(malloc(1));
118 __atexit_invalid = 0;
119 }
120 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
121 MAP_ANON | MAP_PRIVATE, -1, 0);
122 if (p == MAP_FAILED)
123 return;
124 p->ind = 1;
125 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
126 sizeof(p->fns[0]);
127 p->next = NULL;
128 __atexit = p;
129 } else {
130 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
131 return;
132 }
133 p->fns[0] = fn;
134 mprotect(p, pgsize, PROT_READ);
135}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
index 8b756e8fe2..28bf3a7f27 100644
--- a/src/lib/libc/stdlib/atexit.h
+++ b/src/lib/libc/stdlib/atexit.h
@@ -1,46 +1,41 @@
1/*- 1/* $OpenBSD: atexit.h,v 1.5 2002/08/30 07:58:07 dhartmei Exp $ */
2 * Copyright (c) 1990 The Regents of the University of California. 2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 5 * All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
7 * are met: 9 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 * 10 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 11 * - Redistributions of source code must retain the above copyright
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12 * notice, this list of conditions and the following disclaimer.
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13 * - Redistributions in binary form must reproduce the above
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 14 * copyright notice, this list of conditions and the following
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 15 * disclaimer in the documentation and/or other materials provided
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 16 * with the distribution.
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17 *
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * SUCH DAMAGE. 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 * 30 *
33 * from: @(#)atexit.h 5.1 (Berkeley) 5/15/90
34 * $Id: atexit.h,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
35 */ 31 */
36 32
37/* must be at least 32 to guarantee ANSI conformance */
38#define ATEXIT_SIZE 32
39
40struct atexit { 33struct atexit {
41 struct atexit *next; /* next in list */ 34 struct atexit *next; /* next in list */
42 int ind; /* next index in this table */ 35 int ind; /* next index in this table */
43 void (*fns[ATEXIT_SIZE])(); /* the table itself */ 36 int max; /* max entries >= ATEXIT_SIZE */
37 void (*fns[1])(); /* the table itself */
44}; 38};
45 39
40extern int __atexit_invalid;
46extern struct atexit *__atexit; /* points to head of LIFO stack */ 41extern struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
index 53e04f71c5..0bd85dbe82 100644
--- a/src/lib/libc/stdlib/atof.3
+++ b/src/lib/libc/stdlib/atof.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atof.3 6.4 (Berkeley) 6/29/91 36.\" $OpenBSD: atof.3,v 1.3 1999/06/29 18:36:18 aaron Exp $
37.\" $Id: atof.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATOF 3 39.Dt ATOF 3
@@ -52,9 +51,9 @@ string to double
52The 51The
53.Fn atof 52.Fn atof
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Ar nptr 54.Fa nptr
56to 55to
57.Ar double 56.Li double
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
index 9202de50bb..30bac19899 100644
--- a/src/lib/libc/stdlib/atof.c
+++ b/src/lib/libc/stdlib/atof.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atof.c 5.3 (Berkeley) 1/8/93";*/ 35static char *rcsid = "$OpenBSD: atof.c,v 1.2 1996/08/19 08:33:24 tholo Exp $";
36static char *rcsid = "$Id: atof.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
index 219ba73c00..69b94be70c 100644
--- a/src/lib/libc/stdlib/atoi.3
+++ b/src/lib/libc/stdlib/atoi.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atoi.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atoi.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: atoi.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 4, 1993
40.Dt ATOI 3 39.Dt ATOI 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -52,16 +51,27 @@ string to integer
52The 51The
53.Fn atoi 52.Fn atoi
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Em nptr 54.Fa nptr
56to 55to
57.Em integer 56.Li integer
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
61.Pp
62.Bd -literal -offset indent 60.Bd -literal -offset indent
63(int)strtol(nptr, (char **)NULL, 10); 61(int)strtol(nptr, (char **)NULL, 10);
64.Ed 62.Ed
63.Sh CAVEATS
64.Nm
65does no overflow checking, handles unsigned numbers poorly,
66and handles strings containing trailing extra characters
67(like
68.Dq "123abc" Ns )
69poorly.
70Careful use of
71.Xr strtol 3
72and
73.Xr strtoul 3
74can alleviate these problems.
65.Sh SEE ALSO 75.Sh SEE ALSO
66.Xr atof 3 , 76.Xr atof 3 ,
67.Xr atol 3 , 77.Xr atol 3 ,
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
index df7845f90c..a74d6e1351 100644
--- a/src/lib/libc/stdlib/atoi.c
+++ b/src/lib/libc/stdlib/atoi.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atoi.c 5.7 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: atoi.c,v 1.2 1996/08/19 08:33:24 tholo Exp $";
36static char *rcsid = "$Id: atoi.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
index 86e3d324a3..cd276a571f 100644
--- a/src/lib/libc/stdlib/atol.3
+++ b/src/lib/libc/stdlib/atol.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atol.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atol.3,v 1.5 2002/11/21 20:54:09 millert Exp $
37.\" $Id: atol.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATOL 3 39.Dt ATOL 3
@@ -52,9 +51,9 @@ string to long integer
52The 51The
53.Fn atol 52.Fn atol
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Ar nptr 54.Fa nptr
56to 55to
57.Em long integer 56.Li long integer
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
@@ -64,12 +63,12 @@ strtol(nptr, (char **)NULL, 10);
64.Sh SEE ALSO 63.Sh SEE ALSO
65.Xr atof 3 , 64.Xr atof 3 ,
66.Xr atoi 3 , 65.Xr atoi 3 ,
66.Xr atoll 3 ,
67.Xr strtod 3 , 67.Xr strtod 3 ,
68.Xr strtol 3 , 68.Xr strtol 3 ,
69.Xr strtoul 3 69.Xr strtoul 3
70.Sh STANDARDS 70.Sh STANDARDS
71The 71The
72.Fn atol 72.Fn atol
73function 73function conforms to
74conforms to 74.St -ansiC-99 .
75.St -ansiC .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
index 31ed06298b..528a932214 100644
--- a/src/lib/libc/stdlib/atol.c
+++ b/src/lib/libc/stdlib/atol.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atol.c 5.7 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: atol.c,v 1.2 1996/08/19 08:33:26 tholo Exp $";
36static char *rcsid = "$Id: atol.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/calloc.3 b/src/lib/libc/stdlib/atoll.3
index d0754b46a0..8be46407c3 100644
--- a/src/lib/libc/stdlib/calloc.3
+++ b/src/lib/libc/stdlib/atoll.3
@@ -1,4 +1,4 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
@@ -33,39 +33,42 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)calloc.3 5.2 (Berkeley) 6/29/91 36.\" $OpenBSD: atoll.3,v 1.2 2002/11/21 20:54:09 millert Exp $
37.\" $Id: calloc.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt CALLOC 3 39.Dt ATOLL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm calloc 42.Nm atoll
44.Nd allocate clean memory (zero initialized space) 43.Nd convert
44.Tn ASCII
45string to long long integer
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Ft void * 48.Ft long long
48.Fn calloc "size_t nmemb" "size_t size" 49.Fn atoll "const char *nptr"
49.Sh DESCRIPTION 50.Sh DESCRIPTION
50The 51The
51.Fn calloc 52.Fn atoll
52function allocates space for an array of 53function converts the initial portion of the string pointed to by
53.Fa nmemb 54.Fa nptr
54objects, each of whose size is 55to
55.Fa size . 56.Li long integer
56The space is initialized to all bits zero. 57representation.
57.Sh RETURN VALUES 58.Pp
58The 59It is equivalent to:
59.Fn calloc 60.Bd -literal -offset indent
60function returns 61strtoll(nptr, (char **)NULL, 10);
61a pointer to the 62.Ed
62the allocated space if successful; otherwise a null pointer is returned.
63.Sh SEE ALSO 63.Sh SEE ALSO
64.Xr malloc 3 , 64.Xr atof 3 ,
65.Xr realloc 3 , 65.Xr atoi 3 ,
66.Xr free 3 66.Xr atol 3 ,
67.Xr strtod 3 ,
68.Xr strtol 3 ,
69.Xr strtoul 3
67.Sh STANDARDS 70.Sh STANDARDS
68The 71The
69.Fn calloc 72.Fn atoll
70function conforms to 73function conforms to
71.St -ansiC . 74.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000000..63a5b35cd4
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: atoll.c,v 1.1 2002/11/21 20:51:20 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <stdlib.h>
39
40long long
41atoll(str)
42 const char *str;
43{
44 return(strtoll(str, (char **)NULL, 10));
45}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
index 1622c96c6b..9bb9d4ece4 100644
--- a/src/lib/libc/stdlib/bsearch.3
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)bsearch.3 5.6 (Berkeley) 6/29/91 36.\" $OpenBSD: bsearch.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: bsearch.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd April 19, 1994
40.Dt BSEARCH 3 39.Dt BSEARCH 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -51,12 +50,12 @@ The
51.Fn bsearch 50.Fn bsearch
52function searches an array of 51function searches an array of
53.Fa nmemb 52.Fa nmemb
54objects, the initial member of which is 53objects, the initial member of which is
55pointed to by 54pointed to by
56.Fa base , 55.Fa base ,
57for a member that matches the object pointed to by 56for a member that matches the object pointed to by
58.Fa key . 57.Fa key .
59The size of each member of the array is specified by 58The size of each member of the array is specified by
60.Fa size . 59.Fa size .
61.Pp 60.Pp
62The contents of the array should be in ascending sorted order according 61The contents of the array should be in ascending sorted order according
@@ -64,9 +63,7 @@ to the comparison function referenced by
64.Fa compar . 63.Fa compar .
65The 64The
66.Fa compar 65.Fa compar
67routine 66routine is expected to have two arguments which point to the
68is expected to have two
69two arguments which point to the
70.Fa key 67.Fa key
71object and to an array member, in that order, and should return an integer 68object and to an array member, in that order, and should return an integer
72less than, equal to, or greater than zero if the 69less than, equal to, or greater than zero if the
@@ -83,7 +80,7 @@ If two members compare as equal, which member is matched is unspecified.
83.Xr db 3 , 80.Xr db 3 ,
84.Xr lsearch 3 , 81.Xr lsearch 3 ,
85.Xr qsort 3 , 82.Xr qsort 3 ,
86.\" .Xr tsearch 3 83.Xr tsearch 3
87.Sh STANDARDS 84.Sh STANDARDS
88The 85The
89.Fn bsearch 86.Fn bsearch
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
index fac03f694f..1903202b6c 100644
--- a/src/lib/libc/stdlib/bsearch.c
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)bsearch.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: bsearch.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
36static char *rcsid = "$Id: bsearch.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -60,7 +59,7 @@ bsearch(key, base0, nmemb, size, compar)
60 const void *base0; 59 const void *base0;
61 size_t nmemb; 60 size_t nmemb;
62 register size_t size; 61 register size_t size;
63 register int (*compar) __P((const void *, const void *)); 62 register int (*compar)(const void *, const void *);
64{ 63{
65 register const char *base = base0; 64 register const char *base = base0;
66 register int lim, cmp; 65 register int lim, cmp;
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
index 3353fab052..c75b256d14 100644
--- a/src/lib/libc/stdlib/calloc.c
+++ b/src/lib/libc/stdlib/calloc.c
@@ -32,12 +32,13 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)calloc.c 5.6 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: calloc.c,v 1.7 2002/07/31 09:19:04 deraadt Exp $";
36static char *rcsid = "$Id: calloc.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
40#include <limits.h>
41#include <errno.h>
41 42
42void * 43void *
43calloc(num, size) 44calloc(num, size)
@@ -46,8 +47,13 @@ calloc(num, size)
46{ 47{
47 register void *p; 48 register void *p;
48 49
50 if (num && size && SIZE_T_MAX / num < size) {
51 errno = ENOMEM;
52 return NULL;
53 }
49 size *= num; 54 size *= num;
50 if (p = malloc(size)) 55 p = malloc(size);
51 memset(p, '\0', size); 56 if (p)
57 memset(p, 0, size);
52 return(p); 58 return(p);
53} 59}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..3af32039a9
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,49 @@
1/* $OpenBSD: cfree.c,v 1.1 1996/08/21 03:47:22 tholo Exp $ */
2
3/*
4 * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by SigmaSoft, Th. Lockert.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char rcsid[] = "$OpenBSD: cfree.c,v 1.1 1996/08/21 03:47:22 tholo Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/cdefs.h>
38
39#ifdef __indr_reference
40__indr_reference(free, cfree);
41#else
42
43void
44cfree(p)
45 void *p;
46{
47 free(p);
48}
49#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
index a4730694a5..1f651d7fd3 100644
--- a/src/lib/libc/stdlib/div.3
+++ b/src/lib/libc/stdlib/div.3
@@ -31,8 +31,7 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)div.3 5.2 (Berkeley) 4/19/91 34.\" $OpenBSD: div.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
35.\" $Id: div.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt DIV 3 37.Dt DIV 3
@@ -47,24 +46,22 @@
47.Sh DESCRIPTION 46.Sh DESCRIPTION
48The 47The
49.Fn div 48.Fn div
50function 49function computes the value
51computes the value 50.Fa num Ns No / Ns Fa denom
52.Fa num/denom
53and returns the quotient and remainder in a structure named 51and returns the quotient and remainder in a structure named
54.Fa div_t 52.Fa div_t
55that contains two 53that contains two
56.Em int 54.Li int
57members named 55members named
58.Fa quot 56.Fa quot
59and 57and
60.Fa rem . 58.Fa rem .
61.Sh SEE ALSO 59.Sh SEE ALSO
62.Xr ldiv 3 , 60.Xr ldiv 3 ,
63.Xr qdiv 3 , 61.Xr math 3 ,
64.Xr math 3 62.Xr qdiv 3
65.Sh STANDARDS 63.Sh STANDARDS
66The 64The
67.Fn div 65.Fn div
68function 66function conforms to
69conforms to
70.St -ansiC . 67.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
index 122ac0deec..c1fae29008 100644
--- a/src/lib/libc/stdlib/div.c
+++ b/src/lib/libc/stdlib/div.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)div.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: div.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
39static char *rcsid = "$Id: div.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* div_t */ 41#include <stdlib.h> /* div_t */
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
index ae1a8634dc..02886d5b62 100644
--- a/src/lib/libc/stdlib/drand48.c
+++ b/src/lib/libc/stdlib/drand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: drand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..64559ec09e
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,172 @@
1.\" $OpenBSD
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. The name of the author may not be used to endorse or promote products
15.\" derived from this software without specific prior written permission.
16.\"
17.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\"
28.Dd December 1, 2002
29.Dt ECVT 3
30.Os
31.Sh NAME
32.Nm ecvt ,
33.Nm fcvt ,
34.Nm gcvt
35.Nd convert double to
36.Tn ASCII
37string
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft char *
41.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
42.Ft char *
43.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
44.Ft char *
45.Fn gcvt "double value" "int ndigit" "char *buf"
46.Sh DESCRIPTION
47.Bf -symbolic
48These functions are provided for compatibility with legacy code.
49New code should use the
50.Xr snprintf 3
51function for improved safety and portability.
52.Ef
53.Pp
54The
55.Fn ecvt ,
56.Fn fcvt
57and
58.Fn gcvt
59functions convert the double precision floating-point number
60.Fa value
61to a NUL-terminated
62.Tn ASCII
63string.
64.Pp
65The
66.Fn ecvt
67function converts
68.Fa value
69to a NUL-terminated string of exactly
70.Fa ndigit
71digits and returns a pointer to that string.
72The result is padded with zeroes from left to right as needed.
73There are no leading zeroes unless
74.Fa value
75itself is 0.
76The least significant digit is rounded in an implementation-dependent manner.
77The position of the decimal point relative to the beginning of the string
78is stored in
79.Fa decpt .
80A negative value indicates that the decimal point is located
81to the left of the returned digits (this occurs when there is no
82whole number component to
83.Fa value ) .
84If
85.Fa value
86is zero, it is unspecified whether the integer pointed to by
87.Fa decpt
88will be 0 or 1.
89The decimal point itself is not included in the returned string.
90If the sign of the result is negative, the integer pointed to by
91.Fa sign
92is non-zero; otherwise, it is 0.
93.Pp
94If the converted value is out of range or is not representable,
95the contents of the returned string are unspecified.
96.Pp
97The
98.Fn fcvt
99function is identical to
100.Fn ecvt
101with the exception that
102.Fa ndigit
103specifies the number of digits after the decimal point (zero-padded as
104needed).
105.Pp
106The
107.Fn gcvt
108function converts
109.Fa value
110to a NUL-terminated string similar to the %g
111.Xr printf 3
112format specifier and stores the result in
113.Fa buf .
114It produces
115.Fa ndigit
116significant digits similar to the %f
117.Xr printf 3
118format specifier where possible.
119If
120.Fa ndigit
121does allow sufficient precision, the result is stored in
122exponential notation similar to the %e
123.Xr printf 3
124format specifier.
125If
126.Fa value
127is less than zero,
128.Fa buf
129will be prefixed with a minus sign.
130A decimal point is included in the returned string if
131.Fa value
132is not a whole number.
133Unlike the
134.Fn ecvt
135and
136.Fn fcvt
137functions,
138.Fa buf
139is not zero-padded.
140.Sh RETURN VALUES
141The
142.Fn ecvt ,
143.Fn fcvt
144and
145.Fn gcvt
146functions return a NUL-terminated string representation of
147.Fa value .
148.Sh WARNINGS
149The
150.Fn ecvt
151and
152.Fn fcvt
153functions return a pointer to internal storage space that will be
154overwritten by subsequent calls to either function.
155.Pp
156The maximum possible precision of the return value is limited by the
157precision of a double and may not be the same on all architectures.
158.Pp
159The
160.Xr snprintf 3
161function is preferred over these functions for new code.
162.Sh SEE ALSO
163.Xr printf 3 ,
164.Xr strtod 3
165.Sh STANDARDS
166The
167.Fn ecvt ,
168.Fn fcvt
169and
170.Fn gcvt
171functions conform to
172.St -susv3 .
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..7460407c84
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,110 @@
1/* $OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38extern char *__dtoa(double, int, int, int *, int *, char **);
39static char *__cvt(double, int, int *, int *, int, int);
40
41static char *
42__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
43{
44 static char *s;
45 char *p, *rve;
46 size_t siz;
47
48 if (ndigit == 0) {
49 *sign = value < 0.0;
50 *decpt = 0;
51 return ("");
52 }
53
54 if (s) {
55 free(s);
56 s = NULL;
57 }
58
59 if (ndigit < 0)
60 siz = -ndigit + 1;
61 else
62 siz = ndigit + 1;
63
64
65 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
66 if (value == 0.0) {
67 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
68 *sign = 0;
69 if ((rve = s = (char *)malloc(siz)) == NULL)
70 return(NULL);
71 *rve++ = '0';
72 *rve = '\0';
73 } else {
74 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
75 if (*decpt == 9999) {
76 /* Nan or Infinity */
77 *decpt = 0;
78 return(p);
79 }
80 /* make a local copy and adjust rve to be in terms of s */
81 if (pad && fmode)
82 siz += *decpt;
83 if ((s = (char *)malloc(siz)) == NULL)
84 return(NULL);
85 (void) strlcpy(s, p, siz);
86 rve = s + (rve - p);
87 }
88
89 /* Add trailing zeros (unless we got NaN or Inf) */
90 if (pad && *decpt != 9999) {
91 siz -= rve - s;
92 while (--siz)
93 *rve++ = '0';
94 *rve = '\0';
95 }
96
97 return(s);
98}
99
100char *
101ecvt(double value, int ndigit, int *decpt, int *sign)
102{
103 return(__cvt(value, ndigit, decpt, sign, 0, 1));
104}
105
106char *
107fcvt(double value, int ndigit, int *decpt, int *sign)
108{
109 return(__cvt(value, ndigit, decpt, sign, 1, 1));
110}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
index cc9fbf770c..b92dacffcc 100644
--- a/src/lib/libc/stdlib/erand48.c
+++ b/src/lib/libc/stdlib/erand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: erand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16double 20double
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
index adb81ffcb4..fb499e0946 100644
--- a/src/lib/libc/stdlib/exit.3
+++ b/src/lib/libc/stdlib/exit.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)exit.3 6.6 (Berkeley) 6/29/91 36.\" $OpenBSD: exit.3,v 1.8 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: exit.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt EXIT 3 39.Dt EXIT 3
@@ -47,8 +46,9 @@
47.Ft void 46.Ft void
48.Fn exit "int status" 47.Fn exit "int status"
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50.Fn Exit 49The
51terminates a process. 50.Fn exit
51function terminates a process.
52.Pp 52.Pp
53Before termination it performs the following functions in the 53Before termination it performs the following functions in the
54order listed: 54order listed:
@@ -66,19 +66,28 @@ Unlink all files created with the
66.Xr tmpfile 3 66.Xr tmpfile 3
67function. 67function.
68.El 68.El
69.Pp
70Following this,
71.Fn exit
72calls
73.Xr _exit 2 .
74Note that typically
75.Xr _exit 2
76only passes the lower 8 bits of
77.Fa status
78on to the parent, thus negative values have less meaning.
69.Sh RETURN VALUES 79.Sh RETURN VALUES
70The 80The
71.Fn exit 81.Fn exit
72function 82function never returns.
73never returns.
74.Sh SEE ALSO 83.Sh SEE ALSO
75.Xr _exit 2 , 84.Xr _exit 2 ,
76.Xr atexit 3 , 85.Xr atexit 3 ,
77.Xr intro 3 , 86.Xr intro 3 ,
87.Xr sysexits 3 ,
78.Xr tmpfile 3 88.Xr tmpfile 3
79.Sh STANDARDS 89.Sh STANDARDS
80The 90The
81.Fn exit 91.Fn exit
82function 92function conforms to
83conforms to
84.St -ansiC . 93.St -ansiC .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index b1412f42bb..e22bd5178e 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -32,15 +32,24 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)exit.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: exit.c,v 1.8 2002/09/14 22:03:14 dhartmei Exp $";
36static char *rcsid = "$Id: exit.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#include <sys/types.h>
39#include <sys/mman.h>
39#include <stdlib.h> 40#include <stdlib.h>
40#include <unistd.h> 41#include <unistd.h>
41#include "atexit.h" 42#include "atexit.h"
43#include "thread_private.h"
42 44
43void (*__cleanup)(); 45/*
46 * This variable is zero until a process has created a thread.
47 * It is used to avoid calling locking functions in libc when they
48 * are not required. By default, libc is intended to be(come)
49 * thread-safe, but without a (significant) penalty to non-threaded
50 * processes.
51 */
52int __isthreaded = 0;
44 53
45/* 54/*
46 * Exit, flushing stdio buffers if necessary. 55 * Exit, flushing stdio buffers if necessary.
@@ -49,13 +58,20 @@ void
49exit(status) 58exit(status)
50 int status; 59 int status;
51{ 60{
52 register struct atexit *p; 61 register struct atexit *p, *q;
53 register int n; 62 register int n, pgsize = getpagesize();
54 63
55 for (p = __atexit; p; p = p->next) 64 if (!__atexit_invalid) {
56 for (n = p->ind; --n >= 0;) 65 p = __atexit;
57 (*p->fns[n])(); 66 while (p != NULL) {
58 if (__cleanup) 67 for (n = p->ind; --n >= 0;)
59 (*__cleanup)(); 68 if (p->fns[n] != NULL)
69 (*p->fns[n])();
70 q = p;
71 p = p->next;
72 munmap(q, pgsize);
73 }
74 }
75 /* cleanup, if registered, was called through fns[0] in the last page */
60 _exit(status); 76 _exit(status);
61} 77}
diff --git a/src/lib/libc/stdlib/free.3 b/src/lib/libc/stdlib/free.3
deleted file mode 100644
index 3d0131d7de..0000000000
--- a/src/lib/libc/stdlib/free.3
+++ /dev/null
@@ -1,82 +0,0 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission.
23.\"
24.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE.
35.\"
36.\" from: @(#)free.3 5.2 (Berkeley) 6/29/91
37.\" $Id: free.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\"
39.Dd June 29, 1991
40.Dt FREE 3
41.Os
42.Sh NAME
43.Nm free
44.Nd free up memory allocated with malloc, calloc or realloc
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void
48.Fn free "void *ptr"
49.Sh DESCRIPTION
50The
51.Fn free
52function causes the space pointed to by
53.Fa ptr
54to be deallocated, that is, made available
55for further allocation.
56If
57.Fa ptr
58is a null pointer, no action occurs.
59Otherwise, if the argument does not match a pointer earlier
60returned by the
61.Xr calloc ,
62.Xr malloc ,
63or
64.Xr realloc
65function, or if the space has been deallocated by a call to
66.Fn free
67or
68.Xr realloc ,
69general havoc may occur.
70.Sh RETURN VALUES
71The
72.Fn free
73function returns no value.
74.Sh SEE ALSO
75.Xr calloc 3 ,
76.Xr malloc 3 ,
77.Xr realloc 3
78.Sh STANDARDS
79The
80.Fn free
81function conforms to
82.St -ansiC .
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..240c4db5b0
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: gcvt.c,v 1.3 2003/05/09 20:01:43 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: gcvt.c,v 1.3 2003/05/09 20:01:43 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38extern char *__dtoa(double, int, int, int *, int *, char **);
39
40char *
41gcvt(double value, int ndigit, char *buf)
42{
43 char *digits, *dst, *src;
44 int i, decpt, sign;
45
46 if (ndigit == 0) {
47 buf[0] = '\0';
48 return (buf);
49 }
50
51 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
52 if (decpt == 9999) {
53 /* Infinity or NaN, assume buffer is at least ndigit long. */
54 strlcpy(buf, digits, ndigit + 1);
55 return (buf);
56 }
57
58 dst = buf;
59 if (sign)
60 *dst++ = '-';
61
62 if (decpt < 0 || decpt > ndigit) {
63 /* exponential format */
64 if (--decpt < 0) {
65 sign = 1;
66 decpt = -decpt;
67 } else
68 sign = 0;
69 for (src = digits; *src != '\0'; )
70 *dst++ = *src++;
71 *dst++ = 'e';
72 if (sign)
73 *dst++ = '-';
74 else
75 *dst++ = '+';
76 if (decpt < 10) {
77 *dst++ = '0';
78 *dst++ = '0' + decpt;
79 *dst = '\0';
80 } else {
81 /* XXX - optimize */
82 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
83 sign /= 10;
84 while (decpt != 0) {
85 dst[i--] = '0' + decpt % 10;
86 decpt /= 10;
87 }
88 }
89 } else {
90 /* standard format */
91 for (i = 0, src = digits; i < decpt; i++) {
92 if (*src != '\0')
93 *dst++ = *src++;
94 else
95 *dst++ = '0';
96 }
97 if (*src != '\0') {
98 *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
99 for (i = decpt; digits[i] != '\0'; i++) {
100 *dst++ = digits[i];
101 }
102 }
103 *dst = '\0';
104 }
105 return (buf);
106}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
index 411eb35da4..b2aa0080d6 100644
--- a/src/lib/libc/stdlib/getenv.3
+++ b/src/lib/libc/stdlib/getenv.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1988, 1991 The Regents of the University of California. 1.\" Copyright (c) 1988, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)getenv.3 6.11 (Berkeley) 6/29/91 36.\" $OpenBSD: getenv.3,v 1.7 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: getenv.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd December 11, 1993
40.Dt GETENV 3 39.Dt GETENV 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -56,59 +55,51 @@
56.Ft void 55.Ft void
57.Fn unsetenv "const char *name" 56.Fn unsetenv "const char *name"
58.Sh DESCRIPTION 57.Sh DESCRIPTION
59These functions set, unset and fetch environment variables from the 58These functions set, unset, and fetch environment variables from the host
60host
61.Em environment list . 59.Em environment list .
62For compatibility with differing environment conventions, 60For compatibility with differing environment conventions, the given arguments
63the given arguments 61.Fa name
64.Ar name
65and 62and
66.Ar value 63.Fa value
67may be appended and prepended, 64may be appended and prepended, respectively, with an equal sign
68respectively,
69with an equal sign
70.Dq Li \&= . 65.Dq Li \&= .
71.Pp 66.Pp
72The 67The
73.Fn getenv 68.Fn getenv
74function obtains the current value of the environment variable, 69function obtains the current value of the environment variable,
75.Ar name . 70.Fa name .
76If the variable 71If the variable
77.Ar name 72.Fa name
78is not in the current environment , 73is not in the current environment, a null pointer is returned.
79a null pointer is returned.
80.Pp 74.Pp
81The 75The
82.Fn setenv 76.Fn setenv
83function inserts or resets the environment variable 77function inserts or resets the environment variable
84.Ar name 78.Fa name
85in the current environment list. 79in the current environment list.
86If the variable 80If the variable
87.Ar name 81.Fa name
88does not exist in the list, 82does not exist in the list, it is inserted with the given
89it is inserted with the given 83.Fa value .
90.Ar value.
91If the variable does exist, the argument 84If the variable does exist, the argument
92.Ar overwrite 85.Fa overwrite
93is tested; if 86is tested; if
94.Ar overwrite is 87.Fa overwrite
95zero, the 88is zero, the variable is not reset, otherwise it is reset to the given
96variable is not reset, otherwise it is reset 89.Fa value .
97to the given
98.Ar value .
99.Pp 90.Pp
100The 91The
101.Fn putenv 92.Fn putenv
102function takes an argument of the form ``name=value'' and is 93function takes an argument of the form
103equivalent to: 94.Ar name Ns No = Ns Ar value
95and is equivalent to:
104.Bd -literal -offset indent 96.Bd -literal -offset indent
105setenv(name, value, 1); 97setenv(name, value, 1);
106.Ed 98.Ed
107.Pp 99.Pp
108The 100The
109.Fn unsetenv 101.Fn unsetenv
110function 102function deletes all instances of the variable name pointed to by
111deletes all instances of the variable name pointed to by
112.Fa name 103.Fa name
113from the list. 104from the list.
114.Sh RETURN VALUES 105.Sh RETURN VALUES
@@ -118,10 +109,13 @@ and
118.Fn putenv 109.Fn putenv
119return zero if successful; otherwise the global variable 110return zero if successful; otherwise the global variable
120.Va errno 111.Va errno
121is set to indicate the error and a 112is set to indicate the error and \-1 is returned.
122\-1 is returned. 113.Pp
114If
115.Fn getenv
116is successful, the string returned should be considered read-only.
123.Sh ERRORS 117.Sh ERRORS
124.Bl -tag -width Er 118.Bl -tag -width [ENOMEM]
125.It Bq Er ENOMEM 119.It Bq Er ENOMEM
126The function 120The function
127.Fn setenv 121.Fn setenv
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
index 09d47f2149..934f10928f 100644
--- a/src/lib/libc/stdlib/getenv.c
+++ b/src/lib/libc/stdlib/getenv.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 1987 Regents of the University of California. 2 * Copyright (c) 1987, 1993
3 * All rights reserved. 3 * The Regents of the University of California. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -32,26 +32,13 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)getenv.c 5.8 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: getenv.c,v 1.5 2002/12/10 22:44:12 mickey Exp $";
36static char *rcsid = "$Id: getenv.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
41 40
42/* 41char *__findenv(const char *name, int *offset);
43 * getenv --
44 * Returns ptr to value associated with name, if any, else NULL.
45 */
46char *
47getenv(name)
48 const char *name;
49{
50 int offset;
51 char *__findenv();
52
53 return(__findenv(name, &offset));
54}
55 42
56/* 43/*
57 * __findenv -- 44 * __findenv --
@@ -63,20 +50,39 @@ getenv(name)
63 * This routine *should* be a static; don't use it. 50 * This routine *should* be a static; don't use it.
64 */ 51 */
65char * 52char *
66__findenv(name, offset) 53__findenv(const char *name, int *offset)
67 register char *name;
68 int *offset;
69{ 54{
70 extern char **environ; 55 extern char **environ;
71 register int len; 56 register int len, i;
72 register char **P, *C; 57 register const char *np;
58 register char **p, *cp;
59
60 if (name == NULL || environ == NULL)
61 return (NULL);
62 for (np = name; *np && *np != '='; ++np)
63 ;
64 len = np - name;
65 for (p = environ; (cp = *p) != NULL; ++p) {
66 for (np = name, i = len; i && *cp; i--)
67 if (*cp++ != *np++)
68 break;
69 if (i == 0 && *cp++ == '=') {
70 *offset = p - environ;
71 return (cp);
72 }
73 }
74 return (NULL);
75}
76
77/*
78 * getenv --
79 * Returns ptr to value associated with name, if any, else NULL.
80 */
81char *
82getenv(name)
83 const char *name;
84{
85 int offset;
73 86
74 for (C = name, len = 0; *C && *C != '='; ++C, ++len); 87 return (__findenv(name, &offset));
75 for (P = environ; *P; ++P)
76 if (!strncmp(*P, name, len))
77 if (*(C = *P + len) == '=') {
78 *offset = P - environ;
79 return(++C);
80 }
81 return(NULL);
82} 88}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
index f843881afd..d25b497035 100644
--- a/src/lib/libc/stdlib/getopt.3
+++ b/src/lib/libc/stdlib/getopt.3
@@ -29,11 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" @(#)getopt.3 8.4 (Berkeley) 4/19/94 32.\" $OpenBSD: getopt.3,v 1.22 2003/05/10 06:48:30 jmc Exp $
33.\" 33.\"
34.Dd April 19, 1994 34.Dd December 8, 2002
35.Dt GETOPT 3 35.Dt GETOPT 3
36.Os BSD 4.3 36.Os
37.Sh NAME 37.Sh NAME
38.Nm getopt 38.Nm getopt
39.Nd get option character from command line argument list 39.Nd get option character from command line argument list
@@ -51,30 +51,28 @@ The
51.Fn getopt 51.Fn getopt
52function incrementally parses a command line argument list 52function incrementally parses a command line argument list
53.Fa argv 53.Fa argv
54and returns the next 54and returns the next known option character.
55.Em known
56option character.
57An option character is 55An option character is
58.Em known 56.Dq known
59if it has been specified in the string of accepted option characters, 57if it has been specified in the string of accepted option characters,
60.Fa optstring . 58.Fa optstring .
61.Pp 59.Pp
62The option string 60The option string
63.Fa optstring 61.Fa optstring
64may contain the following elements: individual characters, and 62may contain the following elements: individual characters and
65characters followed by a colon to indicate an option argument 63characters followed by a colon to indicate an option argument
66is to follow. 64is to follow.
67For example, an option string 65For example, an option string
68.Li "\&""x"" 66.Qq x
69recognizes an option 67recognizes an option
70.Dq Fl x , 68.Fl x ,
71and an option string 69and an option string
72.Li "\&""x:"" 70.Qq Li x:
73recognizes an option and argument 71recognizes an option and argument
74.Dq Fl x Ar argument . 72.Fl x Ar argument .
75It does not matter to 73It does not matter to
76.Fn getopt 74.Fn getopt
77if a following argument has leading white space. 75if a following argument has leading whitespace.
78.Pp 76.Pp
79On return from 77On return from
80.Fn getopt , 78.Fn getopt ,
@@ -89,12 +87,10 @@ to
89.Fn getopt . 87.Fn getopt .
90The variable 88The variable
91.Va optopt 89.Va optopt
92saves the last 90saves the last known option character returned by
93.Em known
94option character returned by
95.Fn getopt . 91.Fn getopt .
96.Pp 92.Pp
97The variable 93The variables
98.Va opterr 94.Va opterr
99and 95and
100.Va optind 96.Va optind
@@ -119,10 +115,7 @@ must be reinitialized.
119.Pp 115.Pp
120The 116The
121.Fn getopt 117.Fn getopt
122function 118function returns \-1 when the argument list is exhausted.
123returns \-1
124when the argument list is exhausted, or a non-recognized
125option is encountered.
126The interpretation of options in the argument list may be cancelled 119The interpretation of options in the argument list may be cancelled
127by the option 120by the option
128.Ql -- 121.Ql --
@@ -133,49 +126,36 @@ When all options have been processed (i.e., up to the first non-option
133argument), 126argument),
134.Fn getopt 127.Fn getopt
135returns \-1. 128returns \-1.
136.Sh DIAGNOSTICS 129.Sh RETURN VALUES
137If the 130The
138.Fn getopt 131.Fn getopt
139function encounters a character not found in the string 132function returns the next known option character in
140.Va optarg 133.Fa optstring .
141or detects
142a missing option argument it writes an error message and returns
143.Ql ?
144to the
145.Em stderr .
146Setting
147.Va opterr
148to a zero will disable these error messages.
149If 134If
150.Va optstring 135.Fn getopt
151has a leading 136encounters a character not found in
152.Ql \&: 137.Fa optstring
153then a missing option argument causes a 138or if it detects a missing option argument,
154.Ql \&: 139it returns
155to be returned in addition to suppressing any error messages. 140.Sq ? .
156.Pp 141If
157Option arguments are allowed to begin with 142.Fa optstring
158.Dq Li \- ; 143has a leading
159this is reasonable but 144.Sq \:
160reduces the amount of error checking possible. 145then a missing option argument causes
161.Sh EXTENSIONS 146.Sq \:
147to be returned instead of
148.Sq ? .
162The 149The
163.Va optreset
164variable was added to make it possible to call the
165.Fn getopt 150.Fn getopt
166function multiple times. 151function returns \-1 when the argument list is exhausted.
167This is an extension to the 152.Sh EXAMPLES
168.St -p1003.2
169specification.
170.Sh EXAMPLE
171.Bd -literal -compact 153.Bd -literal -compact
172extern char *optarg;
173extern int optind;
174int bflag, ch, fd; 154int bflag, ch, fd;
175 155
176bflag = 0; 156bflag = 0;
177while ((ch = getopt(argc, argv, "bf:")) != -1) 157while ((ch = getopt(argc, argv, "bf:")) != -1) {
178 switch(ch) { 158 switch (ch) {
179 case 'b': 159 case 'b':
180 bflag = 1; 160 bflag = 1;
181 break; 161 break;
@@ -189,31 +169,69 @@ while ((ch = getopt(argc, argv, "bf:")) != -1)
189 case '?': 169 case '?':
190 default: 170 default:
191 usage(); 171 usage();
172 }
192} 173}
193argc -= optind; 174argc -= optind;
194argv += optind; 175argv += optind;
195.Ed 176.Ed
177.Sh SEE ALSO
178.Xr getopt 1 ,
179.Xr getopt_long 3 ,
180.Xr getsubopt 3
181.Sh DIAGNOSTICS
182If the
183.Fn getopt
184function encounters a character not found in the string
185.Va optstring
186or detects
187a missing option argument it writes an error message to
188.Em stderr
189and returns
190.Ql ? .
191Setting
192.Va opterr
193to a zero will disable these error messages.
194If
195.Va optstring
196has a leading
197.Ql \&:
198then a missing option argument causes a
199.Ql \&:
200to be returned in addition to suppressing any error messages.
201.Pp
202Option arguments are allowed to begin with
203.Ql - ;
204this is reasonable but reduces the amount of error checking possible.
205.Sh EXTENSIONS
206The
207.Va optreset
208variable was added to make it possible to call the
209.Fn getopt
210function multiple times.
211This is an extension to the
212.St -p1003.2
213specification.
196.Sh HISTORY 214.Sh HISTORY
197The 215The
198.Fn getopt 216.Fn getopt
199function appeared 217function appeared in
200.Bx 4.3 . 218.Bx 4.3 .
201.Sh BUGS 219.Sh BUGS
202The 220The
203.Fn getopt 221.Fn getopt
204function was once specified to return 222function was once specified to return
205.Dv EOF 223.Dv EOF
206instead of \-1. 224instead of \-1.
207This was changed by 225This was changed by
208.St -p1003.2-92 226.St -p1003.2-92
209to decouple 227to decouple
210.Fn getopt 228.Fn getopt
211from 229from
212.Pa <stdio.h> . 230.Pa <stdio.h> .
213.Pp 231.Pp
214A single dash 232A single dash
215.Dq Li - 233.Pq Ql -
216may be specified as an character in 234may be specified as a character in
217.Fa optstring , 235.Fa optstring ,
218however it should 236however it should
219.Em never 237.Em never
@@ -221,15 +239,25 @@ have an argument associated with it.
221This allows 239This allows
222.Fn getopt 240.Fn getopt
223to be used with programs that expect 241to be used with programs that expect
224.Dq Li - 242.Ql -
225as an option flag. 243as an option flag.
226This practice is wrong, and should not be used in any current development. 244This practice is wrong, and should not be used in any current development.
227It is provided for backward compatibility 245It is provided for backward compatibility
228.Em only . 246.Em only .
247Care should be taken not to use
248.Ql -
249as the first character in
250.Fa optstring
251to avoid a semantic conflict with
252.Tn GNU
253.Fn getopt ,
254which assigns different meaning to an
255.Fa optstring
256that begins with a
257.Ql - .
229By default, a single dash causes 258By default, a single dash causes
230.Fn getopt 259.Fn getopt
231to return \-1. 260to return \-1.
232This is, we believe, compatible with System V.
233.Pp 261.Pp
234It is also possible to handle digits as option letters. 262It is also possible to handle digits as option letters.
235This allows 263This allows
@@ -242,18 +270,19 @@ It is provided for backward compatibility
242.Em only . 270.Em only .
243The following code fragment works in most cases. 271The following code fragment works in most cases.
244.Bd -literal -offset indent 272.Bd -literal -offset indent
245int length; 273int ch;
274long length;
246char *p; 275char *p;
247 276
248while ((c = getopt(argc, argv, "0123456789")) != -1) 277while ((ch = getopt(argc, argv, "0123456789")) != -1) {
249 switch (c) { 278 switch (ch) {
250 case '0': case '1': case '2': case '3': case '4': 279 case '0': case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9': 280 case '5': case '6': case '7': case '8': case '9':
252 p = argv[optind - 1]; 281 p = argv[optind - 1];
253 if (p[0] == '-' && p[1] == ch && !p[2]) 282 if (p[0] == '-' && p[1] == ch && !p[2])
254 length = atoi(++p); 283 length = ch - '0';
255 else 284 else
256 length = atoi(argv[optind] + 1); 285 length = strtol(argv[optind] + 1, NULL, 10);
257 break; 286 break;
258 } 287 }
259} 288}
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
index 63c5e6a479..fc0f8c1bc7 100644
--- a/src/lib/libc/stdlib/getopt.c
+++ b/src/lib/libc/stdlib/getopt.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */ 35static char *rcsid = "$OpenBSD: getopt.c,v 1.4 2002/12/08 22:57:14 millert Exp $";
36static char *rcsid = "$Id: getopt.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdio.h> 38#include <stdio.h>
@@ -64,6 +63,9 @@ getopt(nargc, nargv, ostr)
64 static char *place = EMSG; /* option letter processing */ 63 static char *place = EMSG; /* option letter processing */
65 char *oli; /* option letter list index */ 64 char *oli; /* option letter list index */
66 65
66 if (ostr == NULL)
67 return (-1);
68
67 if (optreset || !*place) { /* update scanning pointer */ 69 if (optreset || !*place) { /* update scanning pointer */
68 optreset = 0; 70 optreset = 0;
69 if (optind >= nargc || *(place = nargv[optind]) != '-') { 71 if (optind >= nargc || *(place = nargv[optind]) != '-') {
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..2589bd7b03
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,373 @@
1.\" $OpenBSD: getopt_long.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
36.\"
37.Dd April 1, 2000
38.Dt GETOPT_LONG 3
39.Os
40.Sh NAME
41.Nm getopt_long ,
42.Nm getopt_long_only
43.Nd get long options from command line argument list
44.Sh SYNOPSIS
45.Fd #include <getopt.h>
46.Vt extern char *optarg;
47.Vt extern int optind;
48.Vt extern int optopt;
49.Vt extern int opterr;
50.Vt extern int optreset;
51.Ft int
52.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *index"
53.Ft int
54.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *index"
55.Sh DESCRIPTION
56The
57.Fn getopt_long
58function is similar to
59.Xr getopt 3
60but it accepts options in two forms: words and characters.
61The
62.Fn getopt_long
63function provides a superset of the functionality of
64.Xr getopt 3 .
65.Fn getopt_long
66can be used in two ways.
67In the first way, every long option understood by the program has a
68corresponding short option, and the option structure is only used to
69translate from long options to short options.
70When used in this fashion,
71.Fn getopt_long
72behaves identically to
73.Xr getopt 3 .
74This is a good way to add long option processing to an existing program
75with the minimum of rewriting.
76.Pp
77In the second mechanism, a long option sets a flag in the
78.Fa option
79structure passed, or will store a pointer to the command line argument
80in the
81.Fa option
82structure passed to it for options that take arguments.
83Additionally, the long option's argument may be specified as a single
84argument with an equal sign, e.g.
85.Bd -literal
86myprogram --myoption=somevalue
87.Ed
88.Pp
89When a long option is processed the call to
90.Fn getopt_long
91will return 0.
92For this reason, long option processing without
93shortcuts is not backwards compatible with
94.Xr getopt 3 .
95.Pp
96It is possible to combine these methods, providing for long options
97processing with short option equivalents for some options.
98Less frequently used options would be processed as long options only.
99.Pp
100The
101.Fn getopt_long
102call requires a structure to be initialized describing the long
103options.
104The structure is:
105.Bd -literal
106struct option {
107 char *name;
108 int has_arg;
109 int *flag;
110 int val;
111};
112.Ed
113.Pp
114The
115.Fa name
116field should contain the option name without the leading double dash.
117.Pp
118The
119.Fa has_arg
120field should be one of:
121.Bl -tag -width "optional_argument"
122.It Li no_argument
123no argument to the option is expect.
124.It Li required_argument
125an argument to the option is required.
126.It Li optional_argument
127an argument to the option may be presented.
128.El
129.Pp
130If
131.Fa flag
132is not
133.Dv NULL ,
134then the integer pointed to by it will be set to the value in the
135.Fa val
136field.
137If the
138.Fa flag
139field is
140.Dv NULL ,
141then the
142.Fa val
143field will be returned.
144Setting
145.Fa flag
146to
147.Dv NULL
148and setting
149.Fa val
150to the corresponding short option will make this function act just
151like
152.Xr getopt 3 .
153.Pp
154The
155.Fn getopt_long_only
156function behaves identically to
157.Fn getopt_long
158with the exception that long options may start with
159.Sq -
160in addition to
161.Sq -- .
162If an option starting with
163.Sq -
164does not match a long option but does match a single-character option,
165the single-character option is returned.
166.Sh RETURN VALUES
167If the
168.Fa flag
169field in
170.Li struct option
171is
172.Dv NULL ,
173.Fn getopt_long
174and
175.Fn getopt_long_only
176return the value specified in the
177.Fa val
178field, which is usually just the corresponding short option.
179If
180.Fa flag
181is not
182.Dv NULL ,
183these functions return 0 and store
184.Fa val
185in the location pointed to by
186.Fa flag .
187These functions return
188.Sq \:
189if there was a missing option argument,
190.Sq ?
191if the user specified an unknown or ambiguous option, and
192\-1 when the argument list has been exhausted.
193.Sh EXAMPLES
194.Bd -literal -compact
195int bflag, ch, fd;
196int daggerset;
197
198/* options descriptor */
199static struct option longopts[] = {
200 { "buffy", no_argument, 0, 'b' },
201 { "fluoride", required_argument, 0, 'f' },
202 { "daggerset", no_argument, &daggerset, 1 },
203 { 0, 0, 0, 0 }
204};
205
206bflag = 0;
207while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
208 switch(ch) {
209 case 'b':
210 bflag = 1;
211 break;
212 case 'f':
213 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
214 err(1, "unable to open %s", optarg);
215 break;
216 case 0:
217 if (daggerset) {
218 fprintf(stderr,"Buffy will use her dagger to "
219 "apply fluoride to dracula's teeth\en");
220 }
221 break;
222 case '?':
223 default:
224 usage();
225}
226argc -= optind;
227argv += optind;
228.Ed
229.Sh IMPLEMENTATION DIFFERENCES
230This section describes differences to the GNU implementation
231found in glibc-2.1.3:
232.Bl -tag -width "xxx"
233.It Li o
234handling of - as first char of option string in presence of
235environment variable POSIXLY_CORRECT:
236.Bl -tag -width "OpenBSD"
237.It Li GNU
238ignores POSIXLY_CORRECT and returns non-options as
239arguments to option '\e1'.
240.It Li OpenBSD
241honors POSIXLY_CORRECT and stops at the first non-option.
242.El
243.It Li o
244handling of - within the option string (not the first character):
245.Bl -tag -width "OpenBSD"
246.It Li GNU
247treats a
248.Ql -
249on the command line as a non-argument.
250.It Li OpenBSD
251a
252.Ql -
253within the option string matches a
254.Ql -
255(single dash) on the command line.
256This functionality is provided for backward compatibility with
257programs, such as
258.Xr su 1 ,
259that use
260.Ql -
261as an option flag.
262This practice is wrong, and should not be used in any current development.
263.El
264.It Li o
265handling of :: in options string in presence of POSIXLY_CORRECT:
266.Bl -tag -width "OpenBSD"
267.It Li Both
268GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
269mean the preceding option takes an optional argument.
270.El
271.It Li o
272return value in case of missing argument if first character
273(after + or -) in option string is not ':':
274.Bl -tag -width "OpenBSD"
275.It Li GNU
276returns '?'
277.It OpenBSD
278returns ':' (since OpenBSD's getopt does).
279.El
280.It Li o
281handling of --a in getopt:
282.Bl -tag -width "OpenBSD"
283.It Li GNU
284parses this as option '-', option 'a'.
285.It Li OpenBSD
286parses this as '--', and returns \-1 (ignoring the a).
287(Because the original getopt does.)
288.El
289.It Li o
290setting of optopt for long options with flag !=
291.Dv NULL :
292.Bl -tag -width "OpenBSD"
293.It Li GNU
294sets optopt to val.
295.It Li OpenBSD
296sets optopt to 0 (since val would never be returned).
297.El
298.It Li o
299handling of -W with W; in option string in getopt (not getopt_long):
300.Bl -tag -width "OpenBSD"
301.It Li GNU
302causes a segfault.
303.It Li OpenBSD
304no special handling is done;
305.Dq W;
306is interpreted as two separate options, neither of which take an argument.
307.El
308.It Li o
309setting of optarg for long options without an argument that are
310invoked via -W (W; in option string):
311.Bl -tag -width "OpenBSD"
312.It Li GNU
313sets optarg to the option name (the argument of -W).
314.It Li OpenBSD
315sets optarg to
316.Dv NULL
317(the argument of the long option).
318.El
319.It Li o
320handling of -W with an argument that is not (a prefix to) a known
321long option (W; in option string):
322.Bl -tag -width "OpenBSD"
323.It Li GNU
324returns -W with optarg set to the unknown option.
325.It Li OpenBSD
326treats this as an error (unknown option) and returns '?' with
327optopt set to 0 and optarg set to
328.Dv NULL
329(as GNU's man page documents).
330.El
331.It Li o
332The error messages are different.
333.It Li o
334OpenBSD does not permute the argument vector at the same points in
335the calling sequence as GNU does.
336The aspects normally used by the caller
337(ordering after \-1 is returned, value of optind relative
338to current positions) are the same, though.
339(We do fewer variable swaps.)
340.El
341.Sh ENVIRONMENT
342.Bl -tag -width POSIXLY_CORRECT
343.It Ev POSIXLY_CORRECT
344If set, option processing stops when the first non-option is found and
345a leading
346.Sq -
347or
348.Sq +
349in the
350.Ar optstring
351is ignored.
352.El
353.Sh SEE ALSO
354.Xr getopt 3
355.Sh HISTORY
356The
357.Fn getopt_long
358and
359.Fn getopt_long_only
360functions first appeared in GNU libiberty.
361This implementation first appeared in
362.Ox 3.3 .
363.Sh BUGS
364The
365.Ar argv
366argument is not really
367.Dv const
368as its elements may be permuted (unless
369.Ev POSIXLY_CORRECT
370is set).
371.Pp
372In a future release, this implementation should completely replace
373.Xr getopt 3 .
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..0cdc4d652f
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,543 @@
1/* $OpenBSD: getopt_long.c,v 1.11 2002/12/10 17:51:42 millert Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3
4/*
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/*-
31 * Copyright (c) 2000 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Dieter Baron and Thomas Klausner.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the NetBSD
48 * Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 * contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65
66#if defined(LIBC_SCCS) && !defined(lint)
67static char *rcsid = "$OpenBSD: getopt_long.c,v 1.11 2002/12/10 17:51:42 millert Exp $";
68#endif /* LIBC_SCCS and not lint */
69
70#include <err.h>
71#include <errno.h>
72#include <getopt.h>
73#include <stdlib.h>
74#include <string.h>
75
76#ifdef REPLACE_GETOPT
77int opterr = 1; /* if error message should be printed */
78int optind = 1; /* index into parent argv vector */
79int optopt = '?'; /* character checked for validity */
80int optreset; /* reset getopt */
81char *optarg; /* argument associated with option */
82#endif
83
84#define PRINT_ERROR ((opterr) && (*options != ':'))
85
86#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
87#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
88#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
89
90/* return values */
91#define BADCH (int)'?'
92#define BADARG ((*options == ':') ? (int)':' : (int)'?')
93#define INORDER (int)1
94
95#define EMSG ""
96
97static int getopt_internal(int, char * const *, const char *,
98 const struct option *, int *, int);
99static int parse_long_options(char * const *, const char *,
100 const struct option *, int *, int);
101static int gcd(int, int);
102static void permute_args(int, int, int, char * const *);
103
104static char *place = EMSG; /* option letter processing */
105
106/* XXX: set optreset to 1 rather than these two */
107static int nonopt_start = -1; /* first non option argument (for permute) */
108static int nonopt_end = -1; /* first option after non options (for permute) */
109
110/* Error messages */
111static const char recargchar[] = "option requires an argument -- %c";
112static const char recargstring[] = "option requires an argument -- %s";
113static const char ambig[] = "ambiguous option -- %.*s";
114static const char noarg[] = "option doesn't take an argument -- %.*s";
115static const char illoptchar[] = "unknown option -- %c";
116static const char illoptstring[] = "unknown option -- %s";
117
118/*
119 * Compute the greatest common divisor of a and b.
120 */
121static int
122gcd(int a, int b)
123{
124 int c;
125
126 c = a % b;
127 while (c != 0) {
128 a = b;
129 b = c;
130 c = a % b;
131 }
132
133 return (b);
134}
135
136/*
137 * Exchange the block from nonopt_start to nonopt_end with the block
138 * from nonopt_end to opt_end (keeping the same order of arguments
139 * in each block).
140 */
141static void
142permute_args(int panonopt_start, int panonopt_end, int opt_end,
143 char * const *nargv)
144{
145 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
146 char *swap;
147
148 /*
149 * compute lengths of blocks and number and size of cycles
150 */
151 nnonopts = panonopt_end - panonopt_start;
152 nopts = opt_end - panonopt_end;
153 ncycle = gcd(nnonopts, nopts);
154 cyclelen = (opt_end - panonopt_start) / ncycle;
155
156 for (i = 0; i < ncycle; i++) {
157 cstart = panonopt_end+i;
158 pos = cstart;
159 for (j = 0; j < cyclelen; j++) {
160 if (pos >= panonopt_end)
161 pos -= nnonopts;
162 else
163 pos += nopts;
164 swap = nargv[pos];
165 /* LINTED const cast */
166 ((char **) nargv)[pos] = nargv[cstart];
167 /* LINTED const cast */
168 ((char **)nargv)[cstart] = swap;
169 }
170 }
171}
172
173/*
174 * parse_long_options --
175 * Parse long options in argc/argv argument vector.
176 * Returns -1 if short_too is set and the option does not match long_options.
177 */
178static int
179parse_long_options(char * const *nargv, const char *options,
180 const struct option *long_options, int *idx, int short_too)
181{
182 char *current_argv, *has_equal;
183 size_t current_argv_len;
184 int i, match;
185
186 current_argv = place;
187 match = -1;
188
189 optind++;
190
191 if ((has_equal = strchr(current_argv, '=')) != NULL) {
192 /* argument found (--option=arg) */
193 current_argv_len = has_equal - current_argv;
194 has_equal++;
195 } else
196 current_argv_len = strlen(current_argv);
197
198 for (i = 0; long_options[i].name; i++) {
199 /* find matching long option */
200 if (strncmp(current_argv, long_options[i].name,
201 current_argv_len))
202 continue;
203
204 if (strlen(long_options[i].name) == current_argv_len) {
205 /* exact match */
206 match = i;
207 break;
208 }
209 /*
210 * If this is a known short option, don't allow
211 * a partial match of a single character.
212 */
213 if (short_too && current_argv_len == 1)
214 continue;
215
216 if (match == -1) /* partial match */
217 match = i;
218 else {
219 /* ambiguous abbreviation */
220 if (PRINT_ERROR)
221 warnx(ambig, (int)current_argv_len,
222 current_argv);
223 optopt = 0;
224 return (BADCH);
225 }
226 }
227 if (match != -1) { /* option found */
228 if (long_options[match].has_arg == no_argument
229 && has_equal) {
230 if (PRINT_ERROR)
231 warnx(noarg, (int)current_argv_len,
232 current_argv);
233 /*
234 * XXX: GNU sets optopt to val regardless of flag
235 */
236 if (long_options[match].flag == NULL)
237 optopt = long_options[match].val;
238 else
239 optopt = 0;
240 return (BADARG);
241 }
242 if (long_options[match].has_arg == required_argument ||
243 long_options[match].has_arg == optional_argument) {
244 if (has_equal)
245 optarg = has_equal;
246 else if (long_options[match].has_arg ==
247 required_argument) {
248 /*
249 * optional argument doesn't use next nargv
250 */
251 optarg = nargv[optind++];
252 }
253 }
254 if ((long_options[match].has_arg == required_argument)
255 && (optarg == NULL)) {
256 /*
257 * Missing argument; leading ':' indicates no error
258 * should be generated.
259 */
260 if (PRINT_ERROR)
261 warnx(recargstring,
262 current_argv);
263 /*
264 * XXX: GNU sets optopt to val regardless of flag
265 */
266 if (long_options[match].flag == NULL)
267 optopt = long_options[match].val;
268 else
269 optopt = 0;
270 --optind;
271 return (BADARG);
272 }
273 } else { /* unknown option */
274 if (short_too) {
275 --optind;
276 return (-1);
277 }
278 if (PRINT_ERROR)
279 warnx(illoptstring, current_argv);
280 optopt = 0;
281 return (BADCH);
282 }
283 if (idx)
284 *idx = match;
285 if (long_options[match].flag) {
286 *long_options[match].flag = long_options[match].val;
287 return (0);
288 } else
289 return (long_options[match].val);
290}
291
292/*
293 * getopt_internal --
294 * Parse argc/argv argument vector. Called by user level routines.
295 */
296static int
297getopt_internal(int nargc, char * const *nargv, const char *options,
298 const struct option *long_options, int *idx, int flags)
299{
300 char *oli; /* option letter list index */
301 int optchar, short_too;
302 static int posixly_correct = -1;
303
304 if (options == NULL)
305 return (-1);
306
307 /*
308 * Disable GNU extensions if POSIXLY_CORRECT is set or options
309 * string begins with a '+'.
310 */
311 if (posixly_correct == -1)
312 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
313 if (posixly_correct || *options == '+')
314 flags &= ~FLAG_PERMUTE;
315 else if (*options == '-')
316 flags |= FLAG_ALLARGS;
317 if (*options == '+' || *options == '-')
318 options++;
319
320 /*
321 * XXX Some GNU programs (like cvs) set optind to 0 instead of
322 * XXX using optreset. Work around this braindamage.
323 */
324 if (optind == 0)
325 optind = optreset = 1;
326
327 optarg = NULL;
328 if (optreset)
329 nonopt_start = nonopt_end = -1;
330start:
331 if (optreset || !*place) { /* update scanning pointer */
332 optreset = 0;
333 if (optind >= nargc) { /* end of argument vector */
334 place = EMSG;
335 if (nonopt_end != -1) {
336 /* do permutation, if we have to */
337 permute_args(nonopt_start, nonopt_end,
338 optind, nargv);
339 optind -= nonopt_end - nonopt_start;
340 }
341 else if (nonopt_start != -1) {
342 /*
343 * If we skipped non-options, set optind
344 * to the first of them.
345 */
346 optind = nonopt_start;
347 }
348 nonopt_start = nonopt_end = -1;
349 return (-1);
350 }
351 if (*(place = nargv[optind]) != '-' ||
352 (place[1] == '\0' && strchr(options, '-') == NULL)) {
353 place = EMSG; /* found non-option */
354 if (flags & FLAG_ALLARGS) {
355 /*
356 * GNU extension:
357 * return non-option as argument to option 1
358 */
359 optarg = nargv[optind++];
360 return (INORDER);
361 }
362 if (!(flags & FLAG_PERMUTE)) {
363 /*
364 * If no permutation wanted, stop parsing
365 * at first non-option.
366 */
367 return (-1);
368 }
369 /* do permutation */
370 if (nonopt_start == -1)
371 nonopt_start = optind;
372 else if (nonopt_end != -1) {
373 permute_args(nonopt_start, nonopt_end,
374 optind, nargv);
375 nonopt_start = optind -
376 (nonopt_end - nonopt_start);
377 nonopt_end = -1;
378 }
379 optind++;
380 /* process next argument */
381 goto start;
382 }
383 if (nonopt_start != -1 && nonopt_end == -1)
384 nonopt_end = optind;
385
386 /*
387 * Check for "--" or "--foo" with no long options
388 * but if place is simply "-" leave it unmolested.
389 */
390 if (place[1] != '\0' && *++place == '-' &&
391 (place[1] == '\0' || long_options == NULL)) {
392 optind++;
393 place = EMSG;
394 /*
395 * We found an option (--), so if we skipped
396 * non-options, we have to permute.
397 */
398 if (nonopt_end != -1) {
399 permute_args(nonopt_start, nonopt_end,
400 optind, nargv);
401 optind -= nonopt_end - nonopt_start;
402 }
403 nonopt_start = nonopt_end = -1;
404 return (-1);
405 }
406 }
407
408 /*
409 * Check long options if:
410 * 1) we were passed some
411 * 2) the arg is not just "-"
412 * 3) either the arg starts with -- we are getopt_long_only()
413 */
414 if (long_options != NULL && place != nargv[optind] &&
415 (*place == '-' || (flags & FLAG_LONGONLY))) {
416 short_too = 0;
417 if (*place == '-')
418 place++; /* --foo long option */
419 else if (*place != ':' && strchr(options, *place) != NULL)
420 short_too = 1; /* could be short option too */
421
422 optchar = parse_long_options(nargv, options, long_options,
423 idx, short_too);
424 if (optchar != -1) {
425 place = EMSG;
426 return (optchar);
427 }
428 }
429
430 if ((optchar = (int)*place++) == (int)':' ||
431 (oli = strchr(options, optchar)) == NULL) {
432 /*
433 * If the user didn't specify '-' as an option,
434 * assume it means -1 as POSIX specifies.
435 */
436 if (optchar == (int)'-')
437 return (-1);
438 /* option letter unknown or ':' */
439 if (!*place)
440 ++optind;
441 if (PRINT_ERROR)
442 warnx(illoptchar, optchar);
443 optopt = optchar;
444 return (BADCH);
445 }
446 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
447 /* -W long-option */
448 if (*place) /* no space */
449 /* NOTHING */;
450 else if (++optind >= nargc) { /* no arg */
451 place = EMSG;
452 if (PRINT_ERROR)
453 warnx(recargchar, optchar);
454 optopt = optchar;
455 return (BADARG);
456 } else /* white space */
457 place = nargv[optind];
458 optchar = parse_long_options(nargv, options, long_options,
459 idx, 0);
460 place = EMSG;
461 return (optchar);
462 }
463 if (*++oli != ':') { /* doesn't take argument */
464 if (!*place)
465 ++optind;
466 } else { /* takes (optional) argument */
467 optarg = NULL;
468 if (*place) /* no white space */
469 optarg = place;
470 /* XXX: disable test for :: if PC? (GNU doesn't) */
471 else if (oli[1] != ':') { /* arg not optional */
472 if (++optind >= nargc) { /* no arg */
473 place = EMSG;
474 if (PRINT_ERROR)
475 warnx(recargchar, optchar);
476 optopt = optchar;
477 return (BADARG);
478 } else
479 optarg = nargv[optind];
480 }
481 place = EMSG;
482 ++optind;
483 }
484 /* dump back option letter */
485 return (optchar);
486}
487
488#ifdef REPLACE_GETOPT
489/*
490 * getopt --
491 * Parse argc/argv argument vector.
492 *
493 * [eventually this will replace the BSD getopt]
494 */
495int
496getopt(int nargc, char * const *nargv, const char *options)
497{
498
499 /*
500 * We dont' pass FLAG_PERMUTE to getopt_internal() since
501 * the BSD getopt(3) (unlike GNU) has never done this.
502 *
503 * Furthermore, since many privileged programs call getopt()
504 * before dropping privileges it makes sense to keep things
505 * as simple (and bug-free) as possible.
506 */
507 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
508}
509#endif /* REPLACE_GETOPT */
510
511/*
512 * getopt_long --
513 * Parse argc/argv argument vector.
514 */
515int
516getopt_long(nargc, nargv, options, long_options, idx)
517 int nargc;
518 char * const *nargv;
519 const char *options;
520 const struct option *long_options;
521 int *idx;
522{
523
524 return (getopt_internal(nargc, nargv, options, long_options, idx,
525 FLAG_PERMUTE));
526}
527
528/*
529 * getopt_long_only --
530 * Parse argc/argv argument vector.
531 */
532int
533getopt_long_only(nargc, nargv, options, long_options, idx)
534 int nargc;
535 char * const *nargv;
536 const char *options;
537 const struct option *long_options;
538 int *idx;
539{
540
541 return (getopt_internal(nargc, nargv, options, long_options, idx,
542 FLAG_PERMUTE|FLAG_LONGONLY));
543}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..e2d8641016
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,147 @@
1.\" $OpenBSD: getsubopt.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
35.\"
36.Dd June 9, 1993
37.Dt GETSUBOPT 3
38.Os
39.Sh NAME
40.Nm getsubopt
41.Nd get sub options from an argument
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Vt extern char *suboptarg;
45.Ft int
46.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
47.Sh DESCRIPTION
48The
49.Fn getsubopt
50function parses a string containing tokens delimited by one or more
51tab, space or comma
52.Pq Ql \&,
53characters.
54It is intended for use in parsing groups of option arguments provided
55as part of a utility command line.
56.Pp
57The argument
58.Fa optionp
59is a pointer to a pointer to the string.
60The argument
61.Fa tokens
62is a pointer to a null-terminated array of pointers to strings.
63.Pp
64The
65.Fn getsubopt
66function returns the zero-based offset of the pointer in the
67.Fa tokens
68array referencing a string which matches the first token
69in the string, or \-1 if the string contains no tokens or
70.Fa tokens
71does not contain a matching string.
72.Pp
73If the token is of the form
74.Ar name Ns No = Ns Ar value ,
75the location referenced by
76.Fa valuep
77will be set to point to the start of the
78.Dq value
79portion of the token.
80.Pp
81On return from
82.Fn getsubopt ,
83.Fa optionp
84will be set to point to the start of the next token in the string,
85or the null at the end of the string if no more tokens are present.
86The external variable
87.Fa suboptarg
88will be set to point to the start of the current token, or
89.Dv NULL
90if no tokens were present.
91The argument
92.Fa valuep
93will be set to point to the value portion of the token, or
94.Dv NULL
95if no value portion was present.
96.Sh EXAMPLES
97.Bd -literal -compact
98char *tokens[] = {
99 #define ONE 0
100 "one",
101 #define TWO 1
102 "two",
103 NULL
104};
105
106\&...
107
108extern char *optarg, *suboptarg;
109char *options, *value;
110
111while ((ch = getopt(argc, argv, "ab:")) != \-1) {
112 switch(ch) {
113 case 'a':
114 /* process ``a'' option */
115 break;
116 case 'b':
117 options = optarg;
118 while (*options) {
119 switch(getsubopt(&options, tokens, &value)) {
120 case ONE:
121 /* process ``one'' sub option */
122 break;
123 case TWO:
124 /* process ``two'' sub option */
125 if (!value)
126 error("no value for two");
127 i = atoi(value);
128 break;
129 case \-1:
130 if (suboptarg)
131 error("illegal sub option %s",
132 suboptarg);
133 else
134 error("missing sub option");
135 break;
136 }
137 break;
138 }
139.Ed
140.Sh SEE ALSO
141.Xr getopt 3 ,
142.Xr strsep 3
143.Sh HISTORY
144The
145.Fn getsubopt
146function first appeared in
147.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/getsubopt.c b/src/lib/libc/stdlib/getsubopt.c
new file mode 100644
index 0000000000..1667a31d7d
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: getsubopt.c,v 1.1 1997/08/20 04:02:17 millert Exp $ */
2
3/*-
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37#if 0
38static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$OpenBSD: getsubopt.c,v 1.1 1997/08/20 04:02:17 millert Exp $";
41#endif
42#endif /* not lint */
43
44#include <unistd.h>
45#include <stdlib.h>
46#include <string.h>
47
48/*
49 * The SVID interface to getsubopt provides no way of figuring out which
50 * part of the suboptions list wasn't matched. This makes error messages
51 * tricky... The extern variable suboptarg is a pointer to the token
52 * which didn't match.
53 */
54char *suboptarg;
55
56int
57getsubopt(optionp, tokens, valuep)
58 register char **optionp, **valuep;
59 register char * const *tokens;
60{
61 register int cnt;
62 register char *p;
63
64 suboptarg = *valuep = NULL;
65
66 if (!optionp || !*optionp)
67 return(-1);
68
69 /* skip leading white-space, commas */
70 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
71
72 if (!*p) {
73 *optionp = p;
74 return(-1);
75 }
76
77 /* save the start of the token, and skip the rest of the token. */
78 for (suboptarg = p;
79 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
80
81 if (*p) {
82 /*
83 * If there's an equals sign, set the value pointer, and
84 * skip over the value part of the token. Terminate the
85 * token.
86 */
87 if (*p == '=') {
88 *p = '\0';
89 for (*valuep = ++p;
90 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
91 if (*p)
92 *p++ = '\0';
93 } else
94 *p++ = '\0';
95 /* Skip any whitespace or commas after this token. */
96 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
97 }
98
99 /* set optionp for next round. */
100 *optionp = p;
101
102 for (cnt = 0; *tokens; ++tokens, ++cnt)
103 if (!strcmp(suboptarg, *tokens))
104 return(cnt);
105 return(-1);
106}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
index bd998fa357..2770e5b977 100644
--- a/src/lib/libc/stdlib/heapsort.c
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)heapsort.c 8.1 (Berkeley) 6/4/93";*/ 38static char *rcsid = "$OpenBSD: heapsort.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
39static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <sys/types.h> 41#include <sys/types.h>
@@ -142,7 +141,7 @@ int
142heapsort(vbase, nmemb, size, compar) 141heapsort(vbase, nmemb, size, compar)
143 void *vbase; 142 void *vbase;
144 size_t nmemb, size; 143 size_t nmemb, size;
145 int (*compar) __P((const void *, const void *)); 144 int (*compar)(const void *, const void *);
146{ 145{
147 register int cnt, i, j, l; 146 register int cnt, i, j, l;
148 register char tmp, *tmp1, *tmp2; 147 register char tmp, *tmp1, *tmp2;
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..b87adb87bc
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.1 2003/05/08 23:26:30 millert Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd August 12, 1993
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.Fd #include <search.h>
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superceded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Sh DIAGNOSTICS
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn lsearch
87and
88.Fn lfind
89functions conform to the
90.St -p1003.1-01
91and
92.St -xpg4.3 .
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the insque and remque instructions on a
100.Tn VAX .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..549246c71f
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43insque(void *entry, void *pred)
44{
45 struct qelem *e = (struct qelem *) entry;
46 struct qelem *p = (struct qelem *) pred;
47
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 p->q_forw->q_back = e;
51 p->q_forw = e;
52}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
index 205781e0ee..99cddb71e5 100644
--- a/src/lib/libc/stdlib/jrand48.c
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: jrand48.c,v 1.2 1996/08/19 08:33:33 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16long 20long
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
index 3069b31bf6..4e99391254 100644
--- a/src/lib/libc/stdlib/l64a.c
+++ b/src/lib/libc/stdlib/l64a.c
@@ -4,13 +4,14 @@
4 */ 4 */
5 5
6#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$NetBSD: l64a.c,v 1.4 1995/05/11 23:04:52 jtc Exp $"; 7static char *rcsid = "$OpenBSD: l64a.c,v 1.3 1997/08/17 22:58:34 millert Exp $";
8#endif 8#endif /* LIBC_SCCS and not lint */
9 9
10#include <errno.h>
10#include <stdlib.h> 11#include <stdlib.h>
11 12
12char * 13char *
13l64a (value) 14l64a(value)
14 long value; 15 long value;
15{ 16{
16 static char buf[8]; 17 static char buf[8];
@@ -18,8 +19,10 @@ l64a (value)
18 int digit; 19 int digit;
19 int i; 20 int i;
20 21
21 if (!value) 22 if (value < 0) {
22 return NULL; 23 errno = EINVAL;
24 return(NULL);
25 }
23 26
24 for (i = 0; value != 0 && i < 6; i++) { 27 for (i = 0; value != 0 && i < 6; i++) {
25 digit = value & 0x3f; 28 digit = value & 0x3f;
@@ -39,5 +42,5 @@ l64a (value)
39 42
40 *s = '\0'; 43 *s = '\0';
41 44
42 return buf; 45 return(buf);
43} 46}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
index 28e4d2053c..fe39ca24dc 100644
--- a/src/lib/libc/stdlib/labs.3
+++ b/src/lib/libc/stdlib/labs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: labs.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: labs.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt LABS 3 39.Dt LABS 3
@@ -49,19 +48,17 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn labs 50.Fn labs
52function 51function returns the absolute value of the long integer
53returns the absolute value of the long integer 52.Fa j .
54.Ar j .
55.Sh SEE ALSO 53.Sh SEE ALSO
56.Xr abs 3 , 54.Xr abs 3 ,
57.Xr floor 3 ,
58.Xr cabs 3 , 55.Xr cabs 3 ,
56.Xr floor 3 ,
59.Xr math 3 57.Xr math 3
60.Sh STANDARDS 58.Sh STANDARDS
61The 59The
62.Fn labs 60.Fn labs
63function 61function conforms to
64conforms to
65.St -ansiC . 62.St -ansiC .
66.Sh BUGS 63.Sh BUGS
67The absolute value of the most negative integer remains negative. 64The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
index ccf1415792..f20e2c29be 100644
--- a/src/lib/libc/stdlib/labs.c
+++ b/src/lib/libc/stdlib/labs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: labs.c,v 1.2 1996/08/19 08:33:34 tholo Exp $";
36static char *rcsid = "$Id: labs.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
index 965d46b17a..44bd74e48a 100644
--- a/src/lib/libc/stdlib/lcong48.c
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lcong48.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
index a7b5ccf878..b5301b1b21 100644
--- a/src/lib/libc/stdlib/ldiv.3
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)ldiv.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: ldiv.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: ldiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt LDIV 3 39.Dt LDIV 3
@@ -49,24 +48,22 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn ldiv 50.Fn ldiv
52function 51function computes the value
53computes the value 52.Fa num Ns No / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 53and returns the quotient and remainder in a structure named
56.Ar ldiv_t 54.Li ldiv_t
57that contains two 55that contains two
58.Em long integer 56.Li long integer
59members named 57members named
60.Ar quot 58.Fa quot
61and 59and
62.Ar rem . 60.Fa rem .
63.Sh SEE ALSO 61.Sh SEE ALSO
64.Xr div 3 , 62.Xr div 3 ,
65.Xr qdiv 3 , 63.Xr math 3 ,
66.Xr math 3 64.Xr qdiv 3
67.Sh STANDARDS 65.Sh STANDARDS
68The 66The
69.Fn ldiv 67.Fn ldiv
70function 68function conforms to
71conforms to
72.St -ansiC . 69.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
index f7074507e5..908c2bf0aa 100644
--- a/src/lib/libc/stdlib/ldiv.c
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: ldiv.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
39static char *rcsid = "$Id: ldiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* ldiv_t */ 41#include <stdlib.h> /* ldiv_t */
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
index 8e7f26237f..6b7524a51b 100644
--- a/src/lib/libc/stdlib/lrand48.c
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lrand48.c,v 1.2 1996/08/19 08:33:36 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/realloc.3 b/src/lib/libc/stdlib/lsearch.3
index 66f09b2081..3e17d131e4 100644
--- a/src/lib/libc/stdlib/realloc.3
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1989, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" Redistribution and use in source and binary forms, with or without 4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 5.\" modification, are permitted provided that the following conditions
@@ -29,72 +29,79 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)realloc.3 5.1 (Berkeley) 5/2/91 32.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
33.\" $Id: realloc.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd June 4, 1993
36.Dt REALLOC 3 35.Dt LSEARCH 3
37.Os 36.Os
38.Sh NAME 37.Sh NAME
39.Nm realloc 38.Nm lsearch ,
40.Nd reallocation of memory function 39.Nm lfind
40.Nd linear searching routines
41.Sh SYNOPSIS 41.Sh SYNOPSIS
42.Fd #include <stdlib.h> 42.Ft char *
43.Ft void * 43.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
44.Fn realloc "void *ptr" "size_t size" 44.Ft char *
45.Fn lfind "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
45.Sh DESCRIPTION 46.Sh DESCRIPTION
47The functions
48.Fn lsearch ,
49and
50.Fn lfind
51provide basic linear searching functionality.
52.Pp
53.Fa base
54is the pointer to the beginning of an array.
55The argument
56.Fa nelp
57is the current number of elements in the array, where each element
58is
59.Fa width
60bytes long.
46The 61The
47.Fn realloc 62.Fa compar
48function changes the size of the object pointed to by 63function
49.Fa ptr 64is a comparison routine which is used to compare two elements.
50to the size specified by 65It takes two arguments which point to the
51.Fa size . 66.Fa key
52The contents of the object are unchanged up to the lesser 67object and to an array member, in that order, and must return an integer
53of the new and old sizes. 68less than, equivalent to, or greater than zero if the
54If the new size is larger, the value of the newly allocated portion 69.Fa key
55of the object is indeterminate. 70object is considered, respectively, to be less than, equal to, or greater
56If 71than the array member.
57.Fa ptr
58is a null pointer, the
59.Fn realloc
60function behaves like the
61.Xr malloc 3
62function for the specified size.
63Otherwise, if
64.Fa ptr
65does not match a pointer earlier returned by the
66.Xr calloc 3 ,
67.Xr malloc 3 ,
68or
69.Fn realloc
70function, or if the space has been deallocated
71by a call to the
72.Xr free
73or
74.Fn realloc
75function, unpredictable and usually detrimental
76behavior will occur.
77If the space cannot be allocated, the object
78pointed to by
79.Fa ptr
80is unchanged.
81If
82.Fa size
83is zero and
84.Fa ptr
85is not a null pointer, the object it points to is freed.
86.Pp 72.Pp
87The 73The
88.Fn realloc 74.Fn lsearch
89function returns either a null pointer or a pointer 75and
90to the possibly moved allocated space. 76.Fn lfind
77functions
78return a pointer into the array referenced by
79.Fa base
80where
81.Fa key
82is located.
83If
84.Fa key
85does not exist,
86.Fn lfind
87will return a null pointer and
88.Fn lsearch
89will add it to the array.
90When an element is added to the array by
91.Fn lsearch
92the location referenced by the argument
93.Fa nelp
94is incremented by one.
91.Sh SEE ALSO 95.Sh SEE ALSO
92.Xr alloca 3 , 96.Xr bsearch 3 ,
93.Xr calloc 3 , 97.Xr db 3
94.Xr free 3 ,
95.Xr malloc 3 ,
96.Sh STANDARDS 98.Sh STANDARDS
97The 99The
98.Fn realloc 100.Fn lsearch
99function conforms to 101and
100.St -ansiC . 102.Fn lfind
103functions conform to the
104.St -p1003.1-01
105and
106.St -xpg4.3 .
107specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..ba0aad3cfc
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Roger L. Snyder.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
39#endif /* LIBC_SCCS and not lint */
40
41#include <sys/types.h>
42#include <string.h>
43#include <search.h>
44
45typedef int (*cmp_fn_t)(const void *, const void *);
46static void *linear_base(const void *, const void *, size_t *, size_t,
47 cmp_fn_t, int);
48
49void *
50lsearch(const void *key, const void *base, size_t *nelp, size_t width,
51 cmp_fn_t compar)
52{
53
54 return(linear_base(key, base, nelp, width, compar, 1));
55}
56
57void *
58lfind(const void *key, const void *base, size_t *nelp, size_t width,
59 cmp_fn_t compar)
60{
61 return(linear_base(key, base, nelp, width, compar, 0));
62}
63
64static void *
65linear_base(const void *key, const void *base, size_t *nelp, size_t width,
66 cmp_fn_t compar, int add_flag)
67{
68 const char *element, *end;
69
70 end = (const char *)base + *nelp * width;
71 for (element = base; element < end; element += width)
72 if (!compar(key, element)) /* key found */
73 return((void *)element);
74
75 if (!add_flag) /* key not found */
76 return(NULL);
77
78 /*
79 * The UNIX System User's Manual, 1986 edition claims that
80 * a NULL pointer is returned by lsearch with errno set
81 * appropriately, if there is not enough room in the table
82 * to add a new item. This can't be done as none of these
83 * routines have any method of determining the size of the
84 * table. This comment isn't in the 1986-87 System V
85 * manual.
86 */
87 ++*nelp;
88 memcpy((void *)end, key, width);
89 return((void *)end);
90}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 3bbf2bf65e..4e31ad4355 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -1,5 +1,6 @@
1.\" Copyright (c) 1980, 1991 Regents of the University of California. 1.\"
2.\" All rights reserved. 2.\" Copyright (c) 1980, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
3.\" 4.\"
4.\" This code is derived from software contributed to Berkeley by 5.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 6.\" the American National Standards Committee X3, on Information
@@ -33,19 +34,32 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 35.\" SUCH DAMAGE.
35.\" 36.\"
36.\" from: @(#)malloc.3 6.7 (Berkeley) 6/29/91 37.\" $OpenBSD: malloc.3,v 1.25 2003/01/21 19:59:09 jmc Exp $
37.\" $Id: malloc.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 38.\"
39.Dd June 29, 1991 39.Dd August 27, 1996
40.Dt MALLOC 3 40.Dt MALLOC 3
41.Os BSD 4 41.Os
42.Sh NAME 42.Sh NAME
43.Nm malloc 43.Nm malloc ,
44.Nd general memory allocation function 44.Nm calloc ,
45.Nm realloc ,
46.Nm free ,
47.Nm cfree
48.Nd memory allocation and deallocation
45.Sh SYNOPSIS 49.Sh SYNOPSIS
46.Fd #include <stdlib.h> 50.Fd #include <stdlib.h>
47.Ft void * 51.Ft void *
48.Fn malloc "size_t size" 52.Fn malloc "size_t size"
53.Ft void *
54.Fn calloc "size_t nmemb" "size_t size"
55.Ft void *
56.Fn realloc "void *ptr" "size_t size"
57.Ft void
58.Fn free "void *ptr"
59.Ft void
60.Fn cfree "void *ptr"
61.Ft char *
62.Va malloc_options
49.Sh DESCRIPTION 63.Sh DESCRIPTION
50The 64The
51.Fn malloc 65.Fn malloc
@@ -59,33 +73,347 @@ space from the appropriate list.
59.Pp 73.Pp
60The allocated space is 74The allocated space is
61suitably aligned (after possible pointer 75suitably aligned (after possible pointer
62coercion) for storage of any type of object. If the space is of 76coercion) for storage of any type of object.
77If the space is of
63.Em pagesize 78.Em pagesize
64or larger, the memory returned will be page-aligned. 79or larger, the memory returned will be page-aligned.
80.Pp
81Allocation of a zero size object returns a pointer to a zero size object.
82This zero size object is access protected, so any access to it will
83generate an exception (SIGSEGV).
84Many zero-sized objects can be placed consecutively in shared
85protected pages.
86The minimum size of the protection on each object is suitably aligned and
87sized as previously stated, but the protection may extend further depending
88on where in a protected zone the object lands.
89.Pp
90The
91.Fn calloc
92function allocates space for an array of
93.Fa nmemb
94objects, each of whose size is
95.Fa size .
96The space is initialized to all bits zero.
97.Pp
98The
99.Fn free
100function causes the space pointed to by
101.Fa ptr
102to be deallocated, that is, at least made available for further allocation,
103but if possible, it will passed back to the kernel with
104.Xr sbrk 2 .
105If
106.Fa ptr
107is a null pointer, no action occurs.
108.Pp
109A
110.Fn cfree
111function is also provided for compatibility with old systems and other
112.Nm malloc
113libraries; it is simply an alias for
114.Fn free .
115.Pp
116The
117.Fn realloc
118function changes the size of the object pointed to by
119.Fa ptr
120to
121.Fa size
122bytes and returns a pointer to the (possibly moved) object.
123The contents of the object are unchanged up to the lesser
124of the new and old sizes.
125If the new size is larger, the value of the newly allocated portion
126of the object is indeterminate and uninitialized.
127If
128.Fa ptr
129is a null pointer, the
130.Fn realloc
131function behaves like the
132.Fn malloc
133function for the specified size.
134If the space cannot be allocated, the object
135pointed to by
136.Fa ptr
137is unchanged.
138If
139.Fa size
140is zero and
141.Fa ptr
142is not a null pointer, the object it points to is freed and a new zero size
143object is returned.
144.Pp
145When using
146.Fn realloc
147one must be careful to avoid the following idiom:
148.Pp
149.Bd -literal -offset indent
150if ((p = realloc(p, nsize)) == NULL)
151 return NULL;
152.Ed
153.Pp
154In most cases, this will result in a leak of memory.
155As stated earlier, a return value of
156.Dv NULL
157indicates that the old object still remains allocated.
158Better code looks like this:
159.Bd -literal -offset indent
160if ((p2 = realloc(p, nsize)) == NULL) {
161 if (p)
162 free(p);
163 p = NULL;
164 return NULL;
165}
166p = p2;
167.Ed
168.Pp
169Malloc will first look for a symbolic link called
170.Pa /etc/malloc.conf
171and next check the environment for a variable called
172.Ev MALLOC_OPTIONS
173and finally for the global variable
174.Va malloc_options
175and scan them for flags in that order.
176Flags are single letters, uppercase means on, lowercase means off.
177.Bl -tag -width indent
178.It Cm A
179.Dq Abort .
180.Fn malloc
181will coredump the process, rather than tolerate failure.
182This is a very handy debugging aid, since the core file will represent the
183time of failure, rather than when the null pointer was accessed.
184.Pp
185.It Cm D
186.Dq Dump .
187.Fn malloc
188will dump statistics in a file called
189.Pa malloc.out
190at exit.
191This option requires the library to have been compiled with -DMALLOC_STATS in
192order to have any effect.
193.Pp
194.It Cm J
195.Dq Junk .
196Fill some junk into the area allocated.
197Currently junk is bytes of 0xd0; this is pronounced
198.Dq Duh .
199\&:-)
200.Pp
201.It Cm H
202.Dq Hint .
203Pass a hint to the kernel about pages we don't use.
204If the machine is paging a lot this may help a bit.
205.Pp
206.It Cm N
207Do not output warning messages when encountering possible corruption
208or bad pointers.
209.Pp
210.It Cm R
211.Dq realloc .
212Always reallocate when
213.Fn realloc
214is called, even if the initial allocation was big enough.
215This can substantially aid in compacting memory.
216.\".Pp
217.\".It Cm U
218.\".Dq utrace .
219.\"Generate entries for
220.\".Xr ktrace 1
221.\"for all operations.
222.\"Consult the source for this one.
223.Pp
224.It Cm X
225.Dq xmalloc .
226Rather than return failure,
227.Xr abort 3
228the program with a diagnostic message on stderr.
229It is the intention that this option be set at compile time by
230including in the source:
231.Bd -literal -offset indent
232extern char *malloc_options;
233malloc_options = "X";
234.Ed
235.Pp
236.It Cm Z
237.Dq Zero .
238Fill some junk into the area allocated (see
239.Cm J ) ,
240except for the exact length the user asked for, which is zeroed.
241.Pp
242.It Cm <
243.Dq Half the cache size .
244Reduce the size of the cache by a factor of two.
245.Pp
246.It Cm >
247.Dq Double the cache size .
248Double the size of the cache by a factor of two.
249.El
250.Pp
251So to set a systemwide reduction of cache size and coredumps on problems
252one would:
253.Li ln -s 'A<' /etc/malloc.conf
254.Pp
255The
256.Cm J
257and
258.Cm Z
259flags are mostly for testing and debugging.
260If a program changes behavior if either of these options are used,
261it is buggy.
262.Pp
263The default cache size is 16 pages.
264.Sh ENVIRONMENT
265See above.
65.Sh RETURN VALUES 266.Sh RETURN VALUES
66The 267The
67.Fn malloc 268.Fn malloc
68function returns 269and
69a pointer to the allocated space if successful; otherwise 270.Fn calloc
70a null pointer is returned. 271functions return a pointer to the allocated space if successful; otherwise,
272a null pointer is returned and
273.Va errno
274is set to
275.Er ENOMEM .
276.Pp
277The
278.Fn free
279and
280.Fn cfree
281functions return no value.
282.Pp
283The
284.Fn realloc
285function returns a pointer to the (possibly moved) allocated space
286if successful; otherwise, a null pointer is returned and
287.Va errno
288is set to
289.Er ENOMEM .
290.Sh DIAGNOSTICS
291If
292.Fn malloc ,
293.Fn calloc ,
294.Fn realloc ,
295or
296.Fn free
297detect an error or warning condition,
298a message will be printed to file descriptor
2992 (not using stdio).
300Errors will always result in the process being
301.Xr abort 3 'ed.
302If the
303.Cm A
304option has been specified, warnings will also
305.Xr abort 3
306the process.
307.Pp
308Here is a brief description of the error messages and what they mean:
309.Bl -tag -width Fl
310.It Dq (ES): mumble mumble mumble
311.Fn malloc
312has been compiled with
313.Dv \&-DEXTRA_SANITY
314and something looks fishy in there.
315Consult sources and/or wizards.
316.It Dq allocation failed
317If the
318.Cm A
319option is specified it is an error for
320.Fn malloc ,
321.Fn calloc ,
322or
323.Fn realloc
324to return
325.Dv NULL .
326.It Dq mmap(2) failed, check limits.
327This is a rather weird condition that is most likely to indicate a
328seriously overloaded system or a
329.Xr ulimit 1
330restriction.
331.It Dq freelist is destroyed.
332.Fn malloc Ns 's
333internal freelist has been stomped on.
334.El
335.Pp
336Here is a brief description of the warning messages and what they mean:
337.Bl -tag -width Fl
338.It Dq chunk/page is already free.
339A pointer to a free chunk is attempted freed again.
340.It Dq junk pointer, too high to make sense.
341The pointer doesn't make sense.
342It's above the area of memory that
343.Fn malloc
344knows something about.
345This could be a pointer from some
346.Xr mmap 2 'ed
347memory.
348.It Dq junk pointer, too low to make sense.
349The pointer doesn't make sense.
350It's below the area of memory that
351.Fn malloc
352knows something about.
353This pointer probably came from your data or bss segments.
354.It Dq malloc() has never been called.
355Nothing has ever been allocated, yet something is being freed or
356realloc'ed.
357.It Dq modified (chunk-/page-) pointer.
358The pointer passed to free or realloc has been modified.
359.It Dq pointer to wrong page.
360The pointer that
361.Fn malloc
362is trying to free is not pointing to
363a sensible page.
364.It Dq recursive call.
365An attempt was made to call recursively into these functions, i.e., from a
366signal handler.
367This behavior is not supported.
368In particular, signal handlers should
369.Em not
370use any of the
371.Fn malloc
372functions nor utilize any other functions which may call
373.Fn malloc
374(e.g.,
375.Xr stdio 3
376routines).
377.It Dq unknown char in MALLOC_OPTIONS
378We found something we didn't understand.
379.El
380.Sh FILES
381.Bl -tag -width "/etc/malloc.conf"
382.It Pa /etc/malloc.conf
383symbolic link to filename containing option flags
384.El
71.Sh SEE ALSO 385.Sh SEE ALSO
72.Xr brk 2 , 386.Xr brk 2 ,
73.Xr getpagesize 2 ,
74.Xr free 3 ,
75.Xr calloc 3 ,
76.Xr alloca 3 , 387.Xr alloca 3 ,
77.Xr realloc 3 , 388.Xr getpagesize 3 ,
78.Xr memory 3 389.Xr memory 3
390.Pa /usr/share/doc/papers/malloc.ascii.gz
79.Sh STANDARDS 391.Sh STANDARDS
80The 392The
81.Fn malloc 393.Fn malloc
82function conforms to 394function conforms to
83.St -ansiC . 395.St -ansiC .
84.Sh BUGS 396.Sh HISTORY
85The current implementation of 397The present implementation of
86.Xr malloc 398.Fn malloc
87does not always fail gracefully when system 399started out as a filesystem on a drum
88memory limits are approached. 400attached to a 20-bit binary challenged computer built with discrete germanium
89It may fail to allocate memory when larger free blocks could be broken 401transistors, and it has since graduated to handle primary storage rather than
90up, or when limits are exceeded because the size is rounded up. 402secondary.
91It is optimized for sizes that are powers of two. 403.Pp
404The main difference from other
405.Fn malloc
406implementations are believed to be that
407the free pages are not accessed until allocated.
408Most
409.Fn malloc
410implementations will store a data structure containing a,
411possibly double-, linked list in the free chunks of memory, used to tie
412all the free memory together.
413That is a quite suboptimal thing to do.
414Every time the free-list is traversed, all the otherwise unused, and very
415likely paged out, pages get faulted into primary memory, just to see what
416lies after them in the list.
417.Pp
418On systems which are paging, this can make a factor five in difference on the
419page-faults of a process.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 3c57fad024..c8aef635d4 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1287 @@
1/* 1/*
2 * Copyright (c) 1983 Regents of the University of California. 2 * ----------------------------------------------------------------------------
3 * All rights reserved. 3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * Redistribution and use in source and binary forms, with or without 5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * modification, are permitted provided that the following conditions 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * are met: 7 * ----------------------------------------------------------------------------
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */ 8 */
33 9
34#if defined(LIBC_SCCS) && !defined(lint) 10#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.54 2003/01/14 02:27:16 millert Exp $";
36static char *rcsid = "$Id: malloc.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
38 13
39/* 14/*
40 * malloc.c (Caltech) 2/21/82 15 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
41 * Chris Kingsley, kingsley@cit-20. 16 * related to internal conditions and consistency in malloc.c. This has
42 * 17 * a noticeable runtime performance hit, and generally will not do you
43 * This is a very fast storage allocator. It allocates blocks of a small 18 * any good unless you fiddle with the internals of malloc or want
44 * number of different sizes, and keeps free lists of each size. Blocks that 19 * to catch random pointer corruption as early as possible.
45 * don't exactly fit are passed up to the next larger size. In this 20 */
46 * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. 21#ifndef MALLOC_EXTRA_SANITY
47 * This is designed for use in a virtual memory environment. 22#undef MALLOC_EXTRA_SANITY
23#endif
24
25/*
26 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
27 * the [dD] options in the MALLOC_OPTIONS environment variable.
28 * It has no run-time performance hit, but does pull in stdio...
29 */
30#ifndef MALLOC_STATS
31#undef MALLOC_STATS
32#endif
33
34/*
35 * What to use for Junk. This is the byte value we use to fill with
36 * when the 'J' option is enabled.
48 */ 37 */
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
49 39
50#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/param.h>
42#include <sys/mman.h>
43#include <sys/uio.h>
44#include <stdio.h>
51#include <stdlib.h> 45#include <stdlib.h>
52#include <string.h> 46#include <string.h>
53#include <unistd.h> 47#include <unistd.h>
48#include <fcntl.h>
49#include <limits.h>
50#include <errno.h>
51
52#include "thread_private.h"
54 53
55#define NULL 0 54/*
55 * The basic parameters you can tweak.
56 *
57 * malloc_pageshift pagesize = 1 << malloc_pageshift
58 * It's probably best if this is the native
59 * page size, but it shouldn't have to be.
60 *
61 * malloc_minsize minimum size of an allocation in bytes.
62 * If this is too small it's too much work
63 * to manage them. This is also the smallest
64 * unit of alignment used for the storage
65 * returned by malloc/realloc.
66 *
67 */
56 68
57static void morecore(); 69#if defined(__OpenBSD__) && defined(__sparc__)
58static int findbucket(); 70# define malloc_pageshift 13U
71#endif /* __OpenBSD__ */
59 72
60/* 73/*
61 * The overhead on a block is at least 4 bytes. When free, this space 74 * No user serviceable parts behind this point.
62 * contains a pointer to the next free block, and the bottom two bits must 75 *
63 * be zero. When in use, the first byte is set to MAGIC, and the second 76 * This structure describes a page worth of chunks.
64 * byte is the size index. The remaining bytes are for alignment.
65 * If range checking is enabled then a second word holds the size of the
66 * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
67 * The order of elements is critical: ov_magic must overlay the low order
68 * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
69 */ 77 */
70union overhead { 78
71 union overhead *ov_next; /* when free */ 79struct pginfo {
72 struct { 80 struct pginfo *next; /* next on the free list */
73 u_char ovu_magic; /* magic number */ 81 void *page; /* Pointer to the page */
74 u_char ovu_index; /* bucket # */ 82 u_short size; /* size of this page's chunks */
75#ifdef RCHECK 83 u_short shift; /* How far to shift for this size chunks */
76 u_short ovu_rmagic; /* range magic number */ 84 u_short free; /* How many free chunks */
77 u_long ovu_size; /* actual block size */ 85 u_short total; /* How many chunk */
78#endif 86 u_long bits[1]; /* Which chunks are free */
79 } ovu;
80#define ov_magic ovu.ovu_magic
81#define ov_index ovu.ovu_index
82#define ov_rmagic ovu.ovu_rmagic
83#define ov_size ovu.ovu_size
84}; 87};
85 88
86#define MAGIC 0xef /* magic # on accounting info */ 89/*
87#define RMAGIC 0x5555 /* magic # on range info */ 90 * This structure describes a number of free pages.
91 */
92
93struct pgfree {
94 struct pgfree *next; /* next run of free pages */
95 struct pgfree *prev; /* prev run of free pages */
96 void *page; /* pointer to free pages */
97 void *end; /* pointer to end of free pages */
98 u_long size; /* number of bytes free */
99};
88 100
89#ifdef RCHECK 101/*
90#define RSLOP sizeof (u_short) 102 * How many bits per u_long in the bitmap.
103 * Change only if not 8 bits/byte
104 */
105#define MALLOC_BITS (8*sizeof(u_long))
106
107/*
108 * Magic values to put in the page_directory
109 */
110#define MALLOC_NOT_MINE ((struct pginfo*) 0)
111#define MALLOC_FREE ((struct pginfo*) 1)
112#define MALLOC_FIRST ((struct pginfo*) 2)
113#define MALLOC_FOLLOW ((struct pginfo*) 3)
114#define MALLOC_MAGIC ((struct pginfo*) 4)
115
116#ifndef malloc_pageshift
117#define malloc_pageshift (PGSHIFT)
118#endif
119
120#ifndef malloc_minsize
121#define malloc_minsize 16U
122#endif
123
124#ifndef malloc_pageshift
125#error "malloc_pageshift undefined"
126#endif
127
128#if !defined(malloc_pagesize)
129#define malloc_pagesize (1UL<<malloc_pageshift)
130#endif
131
132#if ((1UL<<malloc_pageshift) != malloc_pagesize)
133#error "(1UL<<malloc_pageshift) != malloc_pagesize"
134#endif
135
136#ifndef malloc_maxsize
137#define malloc_maxsize ((malloc_pagesize)>>1)
138#endif
139
140/* A mask for the offset inside a page. */
141#define malloc_pagemask ((malloc_pagesize)-1)
142
143#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
144#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
145
146/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO
148static int fdzero;
149#define MMAP_FD fdzero
150#define INIT_MMAP() \
151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
152 wrterror("open of /dev/zero"); }
91#else 153#else
92#define RSLOP 0 154#define MMAP_FD (-1)
155#define INIT_MMAP()
93#endif 156#endif
94 157
158/* Set when initialization has been done */
159static unsigned int malloc_started;
160
161/* Number of free pages we cache */
162static unsigned int malloc_cache = 16;
163
164/* The offset from pagenumber to index into the page directory */
165static u_long malloc_origo;
166
167/* The last index in the page directory we care about */
168static u_long last_index;
169
170/* Pointer to page directory. Allocated "as if with" malloc */
171static struct pginfo **page_dir;
172
173/* How many slots in the page directory */
174static size_t malloc_ninfo;
175
176/* Free pages line up here */
177static struct pgfree free_list;
178
179/* Abort(), user doesn't handle problems. */
180static int malloc_abort;
181
182/* Are we trying to die ? */
183static int suicide;
184
185#ifdef MALLOC_STATS
186/* dump statistics */
187static int malloc_stats;
188#endif
189
190/* avoid outputting warnings? */
191static int malloc_silent;
192
193/* always realloc ? */
194static int malloc_realloc;
195
196#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
197/* pass the kernel a hint on free pages ? */
198static int malloc_hint;
199#endif
200
201/* xmalloc behaviour ? */
202static int malloc_xmalloc;
203
204/* zero fill ? */
205static int malloc_zero;
206
207/* junk fill ? */
208static int malloc_junk;
209
210#ifdef __FreeBSD__
211/* utrace ? */
212static int malloc_utrace;
213
214struct ut { void *p; size_t s; void *r; };
215
216void utrace(struct ut *, int);
217
218#define UTRACE(a, b, c) \
219 if (malloc_utrace) \
220 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
221#else /* !__FreeBSD__ */
222#define UTRACE(a,b,c)
223#endif
224
225/* my last break. */
226static void *malloc_brk;
227
228/* one location cache for free-list holders */
229static struct pgfree *px;
230
231/* compile-time options */
232char *malloc_options;
233
234/* Name of the current public function */
235static char *malloc_func;
236
237/* Macro for mmap */
238#define MMAP(size) \
239 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
240 MMAP_FD, (off_t)0);
241
95/* 242/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 243 * Necessary function declarations
97 * smallest allocatable block is 8 bytes. The overhead information
98 * precedes the data area returned to the user.
99 */ 244 */
100#define NBUCKETS 30 245static int extend_pgdir(u_long index);
101static union overhead *nextf[NBUCKETS]; 246static void *imalloc(size_t size);
102extern char *sbrk(); 247static void ifree(void *ptr);
248static void *irealloc(void *ptr, size_t size);
249static void *malloc_bytes(size_t size);
250
251#ifdef MALLOC_STATS
252void
253malloc_dump(fd)
254 FILE *fd;
255{
256 struct pginfo **pd;
257 struct pgfree *pf;
258 int j;
259
260 pd = page_dir;
261
262 /* print out all the pages */
263 for(j=0;j<=last_index;j++) {
264 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
265 if (pd[j] == MALLOC_NOT_MINE) {
266 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
267 ;
268 j--;
269 fprintf(fd, ".. %5d not mine\n", j);
270 } else if (pd[j] == MALLOC_FREE) {
271 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
272 ;
273 j--;
274 fprintf(fd, ".. %5d free\n", j);
275 } else if (pd[j] == MALLOC_FIRST) {
276 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
277 ;
278 j--;
279 fprintf(fd, ".. %5d in use\n", j);
280 } else if (pd[j] < MALLOC_MAGIC) {
281 fprintf(fd, "(%p)\n", pd[j]);
282 } else {
283 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
284 pd[j], pd[j]->free, pd[j]->total,
285 pd[j]->size, pd[j]->page, pd[j]->next);
286 }
287 }
288
289 for(pf=free_list.next; pf; pf=pf->next) {
290 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
291 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
292 if (pf == pf->next) {
293 fprintf(fd, "Free_list loops.\n");
294 break;
295 }
296 }
297
298 /* print out various info */
299 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
300 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
301 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
302 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
303 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
304 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
305 (last_index + malloc_pageshift) << malloc_pageshift);
306 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
307}
308#endif /* MALLOC_STATS */
309
310extern char *__progname;
311
312static void
313wrterror(p)
314 char *p;
315{
316 char *q = " error: ";
317 struct iovec iov[4];
318
319 iov[0].iov_base = __progname;
320 iov[0].iov_len = strlen(__progname);
321 iov[1].iov_base = malloc_func;
322 iov[1].iov_len = strlen(malloc_func);
323 iov[2].iov_base = q;
324 iov[2].iov_len = strlen(q);
325 iov[3].iov_base = p;
326 iov[3].iov_len = strlen(p);
327 writev(STDERR_FILENO, iov, 4);
328
329 suicide = 1;
330#ifdef MALLOC_STATS
331 if (malloc_stats)
332 malloc_dump(stderr);
333#endif /* MALLOC_STATS */
334 abort();
335}
336
337static void
338wrtwarning(p)
339 char *p;
340{
341 char *q = " warning: ";
342 struct iovec iov[4];
343
344 if (malloc_abort)
345 wrterror(p);
346 else if (malloc_silent)
347 return;
348
349 iov[0].iov_base = __progname;
350 iov[0].iov_len = strlen(__progname);
351 iov[1].iov_base = malloc_func;
352 iov[1].iov_len = strlen(malloc_func);
353 iov[2].iov_base = q;
354 iov[2].iov_len = strlen(q);
355 iov[3].iov_base = p;
356 iov[3].iov_len = strlen(p);
357 writev(STDERR_FILENO, iov, 4);
358}
359
360#ifdef MALLOC_STATS
361static void
362malloc_exit()
363{
364 FILE *fd = fopen("malloc.out", "a");
365 char *q = "malloc() warning: Couldn't dump stats.\n";
366 if (fd) {
367 malloc_dump(fd);
368 fclose(fd);
369 } else
370 write(STDERR_FILENO, q, strlen(q));
371}
372#endif /* MALLOC_STATS */
103 373
104static int pagesz; /* page size */
105static int pagebucket; /* page size bucket */
106 374
107#ifdef MSTATS
108/* 375/*
109 * nmalloc[i] is the difference between the number of mallocs and frees 376 * Allocate a number of pages from the OS
110 * for a given block size.
111 */ 377 */
112static u_int nmalloc[NBUCKETS]; 378static void *
113#include <stdio.h> 379map_pages(pages)
114#endif 380 size_t pages;
381{
382 caddr_t result, tail;
115 383
116#if defined(DEBUG) || defined(RCHECK) 384 result = (caddr_t)pageround((u_long)sbrk(0));
117#define ASSERT(p) if (!(p)) botch("p") 385 pages <<= malloc_pageshift;
118#include <stdio.h> 386 if (pages > SIZE_T_MAX - (size_t)result) {
119static 387#ifdef MALLOC_EXTRA_SANITY
120botch(s) 388 wrterror("(ES): overflow in map_pages fails\n");
121 char *s; 389#endif /* MALLOC_EXTRA_SANITY */
390 return 0;
391 }
392 tail = result + pages;
393
394 if (brk(tail)) {
395#ifdef MALLOC_EXTRA_SANITY
396 wrterror("(ES): map_pages fails\n");
397#endif /* MALLOC_EXTRA_SANITY */
398 return 0;
399 }
400
401 last_index = ptr2index(tail) - 1;
402 malloc_brk = tail;
403
404 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
405 return 0;
406
407 return result;
408}
409
410/*
411 * Extend page directory
412 */
413static int
414extend_pgdir(index)
415 u_long index;
122{ 416{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 417 struct pginfo **new, **old;
124 (void) fflush(stderr); /* just in case user buffered it */ 418 size_t i, oldlen;
125 abort(); 419
420 /* Make it this many pages */
421 i = index * sizeof *page_dir;
422 i /= malloc_pagesize;
423 i += 2;
424
425 /* remember the old mapping size */
426 oldlen = malloc_ninfo * sizeof *page_dir;
427
428 /*
429 * NOTE: we allocate new pages and copy the directory rather than tempt
430 * fate by trying to "grow" the region.. There is nothing to prevent
431 * us from accidently re-mapping space that's been allocated by our caller
432 * via dlopen() or other mmap().
433 *
434 * The copy problem is not too bad, as there is 4K of page index per
435 * 4MB of malloc arena.
436 *
437 * We can totally avoid the copy if we open a file descriptor to associate
438 * the anon mappings with. Then, when we remap the pages at the new
439 * address, the old pages will be "magically" remapped.. But this means
440 * keeping open a "secret" file descriptor.....
441 */
442
443 /* Get new pages */
444 new = (struct pginfo**) MMAP(i * malloc_pagesize);
445 if (new == MAP_FAILED)
446 return 0;
447
448 /* Copy the old stuff */
449 memcpy(new, page_dir,
450 malloc_ninfo * sizeof *page_dir);
451
452 /* register the new size */
453 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
454
455 /* swap the pointers */
456 old = page_dir;
457 page_dir = new;
458
459 /* Now free the old stuff */
460 munmap(old, oldlen);
461 return 1;
126} 462}
127#else
128#define ASSERT(p)
129#endif
130 463
131void * 464/*
132malloc(nbytes) 465 * Initialize the world
133 size_t nbytes; 466 */
467static void
468malloc_init ()
134{ 469{
135 register union overhead *op; 470 char *p, b[64];
136 register long bucket, n; 471 int i, j;
137 register unsigned amt; 472 int save_errno = errno;
138 473
139 /* 474 _MALLOC_LOCK_INIT();
140 * First time malloc is called, setup page size and 475
141 * align break pointer so all data will be page aligned. 476 INIT_MMAP();
142 */ 477
143 if (pagesz == 0) { 478#ifdef MALLOC_EXTRA_SANITY
144 pagesz = n = getpagesize(); 479 malloc_junk = 1;
145 op = (union overhead *)sbrk(0); 480#endif /* MALLOC_EXTRA_SANITY */
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 481
147 if (n < 0) 482 for (i = 0; i < 3; i++) {
148 n += pagesz; 483 if (i == 0) {
149 if (n) { 484 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
150 if (sbrk(n) == (char *)-1) 485 if (j <= 0)
151 return (NULL); 486 continue;
152 } 487 b[j] = '\0';
153 bucket = 0; 488 p = b;
154 amt = 8; 489 } else if (i == 1) {
155 while (pagesz > amt) { 490 if (issetugid() == 0)
156 amt <<= 1; 491 p = getenv("MALLOC_OPTIONS");
157 bucket++; 492 else
158 } 493 continue;
159 pagebucket = bucket; 494 } else if (i == 2) {
160 } 495 p = malloc_options;
161 /*
162 * Convert amount of memory requested into closest block size
163 * stored in hash buckets which satisfies request.
164 * Account for space used per block for accounting.
165 */
166 if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
167#ifndef RCHECK
168 amt = 8; /* size of first bucket */
169 bucket = 0;
170#else
171 amt = 16; /* size of first bucket */
172 bucket = 1;
173#endif
174 n = -((long)sizeof (*op) + RSLOP);
175 } else {
176 amt = pagesz;
177 bucket = pagebucket;
178 } 496 }
179 while (nbytes > amt + n) { 497 for (; p && *p; p++) {
180 amt <<= 1; 498 switch (*p) {
181 if (amt == 0) 499 case '>': malloc_cache <<= 1; break;
182 return (NULL); 500 case '<': malloc_cache >>= 1; break;
183 bucket++; 501 case 'a': malloc_abort = 0; break;
502 case 'A': malloc_abort = 1; break;
503#ifdef MALLOC_STATS
504 case 'd': malloc_stats = 0; break;
505 case 'D': malloc_stats = 1; break;
506#endif /* MALLOC_STATS */
507#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
508 case 'h': malloc_hint = 0; break;
509 case 'H': malloc_hint = 1; break;
510#endif /* __FreeBSD__ */
511 case 'r': malloc_realloc = 0; break;
512 case 'R': malloc_realloc = 1; break;
513 case 'j': malloc_junk = 0; break;
514 case 'J': malloc_junk = 1; break;
515 case 'n': malloc_silent = 0; break;
516 case 'N': malloc_silent = 1; break;
517#ifdef __FreeBSD__
518 case 'u': malloc_utrace = 0; break;
519 case 'U': malloc_utrace = 1; break;
520#endif /* __FreeBSD__ */
521 case 'x': malloc_xmalloc = 0; break;
522 case 'X': malloc_xmalloc = 1; break;
523 case 'z': malloc_zero = 0; break;
524 case 'Z': malloc_zero = 1; break;
525 default:
526 j = malloc_abort;
527 malloc_abort = 0;
528 wrtwarning("unknown char in MALLOC_OPTIONS\n");
529 malloc_abort = j;
530 break;
531 }
184 } 532 }
185 /* 533 }
186 * If nothing in hash bucket right now, 534
187 * request more memory from the system. 535 UTRACE(0, 0, 0);
188 */ 536
189 if ((op = nextf[bucket]) == NULL) { 537 /*
190 morecore(bucket); 538 * We want junk in the entire allocation, and zero only in the part
191 if ((op = nextf[bucket]) == NULL) 539 * the user asked for.
192 return (NULL); 540 */
541 if (malloc_zero)
542 malloc_junk=1;
543
544#ifdef MALLOC_STATS
545 if (malloc_stats && (atexit(malloc_exit) == -1))
546 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit.\n");
547#endif /* MALLOC_STATS */
548
549 /* Allocate one page for the page directory */
550 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
551
552 if (page_dir == MAP_FAILED)
553 wrterror("mmap(2) failed, check limits.\n");
554
555 /*
556 * We need a maximum of malloc_pageshift buckets, steal these from the
557 * front of the page_directory;
558 */
559 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
560 malloc_origo -= malloc_pageshift;
561
562 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
563
564 /* Been here, done that */
565 malloc_started++;
566
567 /* Recalculate the cache size in bytes, and make sure it's nonzero */
568
569 if (!malloc_cache)
570 malloc_cache++;
571
572 malloc_cache <<= malloc_pageshift;
573
574 /*
575 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
576 * We can sbrk(2) further back when we keep this on a low address.
577 */
578 px = (struct pgfree *) imalloc (sizeof *px);
579 errno = save_errno;
580}
581
582/*
583 * Allocate a number of complete pages
584 */
585static void *
586malloc_pages(size)
587 size_t size;
588{
589 void *p, *delay_free = 0;
590 int i;
591 struct pgfree *pf;
592 u_long index;
593
594 size = pageround(size);
595
596 p = 0;
597 /* Look for free pages before asking for more */
598 for(pf = free_list.next; pf; pf = pf->next) {
599
600#ifdef MALLOC_EXTRA_SANITY
601 if (pf->size & malloc_pagemask)
602 wrterror("(ES): junk length entry on free_list\n");
603 if (!pf->size)
604 wrterror("(ES): zero length entry on free_list\n");
605 if (pf->page == pf->end)
606 wrterror("(ES): zero entry on free_list\n");
607 if (pf->page > pf->end)
608 wrterror("(ES): sick entry on free_list\n");
609 if ((void*)pf->page >= (void*)sbrk(0))
610 wrterror("(ES): entry on free_list past brk\n");
611 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
612 wrterror("(ES): non-free first page on free-list\n");
613 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
614 wrterror("(ES): non-free last page on free-list\n");
615#endif /* MALLOC_EXTRA_SANITY */
616
617 if (pf->size < size)
618 continue;
619
620 if (pf->size == size) {
621 p = pf->page;
622 if (pf->next)
623 pf->next->prev = pf->prev;
624 pf->prev->next = pf->next;
625 delay_free = pf;
626 break;
193 } 627 }
194 /* remove from linked list */ 628
195 nextf[bucket] = op->ov_next; 629 p = pf->page;
196 op->ov_magic = MAGIC; 630 pf->page = (char *)pf->page + size;
197 op->ov_index = bucket; 631 pf->size -= size;
198#ifdef MSTATS 632 break;
199 nmalloc[bucket]++; 633 }
200#endif 634
201#ifdef RCHECK 635#ifdef MALLOC_EXTRA_SANITY
202 /* 636 if (p && page_dir[ptr2index(p)] != MALLOC_FREE)
203 * Record allocated size of block and 637 wrterror("(ES): allocated non-free page on free-list\n");
204 * bound space with magic numbers. 638#endif /* MALLOC_EXTRA_SANITY */
205 */ 639
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 640 size >>= malloc_pageshift;
207 op->ov_rmagic = RMAGIC; 641
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 642 /* Map new pages */
209#endif 643 if (!p)
210 return ((char *)(op + 1)); 644 p = map_pages(size);
645
646 if (p) {
647
648 index = ptr2index(p);
649 page_dir[index] = MALLOC_FIRST;
650 for (i=1;i<size;i++)
651 page_dir[index+i] = MALLOC_FOLLOW;
652
653 if (malloc_junk)
654 memset(p, SOME_JUNK, size << malloc_pageshift);
655 }
656
657 if (delay_free) {
658 if (!px)
659 px = delay_free;
660 else
661 ifree(delay_free);
662 }
663
664 return p;
211} 665}
212 666
213/* 667/*
214 * Allocate more memory to the indicated bucket. 668 * Allocate a page of fragments
215 */ 669 */
216static void 670
217morecore(bucket) 671static __inline__ int
218 int bucket; 672malloc_make_chunks(bits)
673 int bits;
219{ 674{
220 register union overhead *op; 675 struct pginfo *bp;
221 register long sz; /* size of desired block */ 676 void *pp;
222 long amt; /* amount to allocate */ 677 int i, k, l;
223 int nblks; /* how many blocks we get */
224 678
225 /* 679 /* Allocate a new bucket */
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 680 pp = malloc_pages((size_t)malloc_pagesize);
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 681 if (!pp)
228 */ 682 return 0;
229 sz = 1 << (bucket + 3); 683
230#ifdef DEBUG 684 /* Find length of admin structure */
231 ASSERT(sz > 0); 685 l = sizeof *bp - sizeof(u_long);
232#else 686 l += sizeof(u_long) *
233 if (sz <= 0) 687 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
234 return; 688
235#endif 689 /* Don't waste more than two chunks on this */
236 if (sz < pagesz) { 690 /*
237 amt = pagesz; 691 * If we are to allocate a memory protected page for the malloc(0)
238 nblks = amt / sz; 692 * case (when bits=0), it must be from a different page than the
239 } else { 693 * pginfo page.
240 amt = sz + pagesz; 694 * --> Treat it like the big chunk alloc, get a second data page.
241 nblks = 1; 695 */
696 if (bits != 0 && (1UL<<(bits)) <= l+l) {
697 bp = (struct pginfo *)pp;
698 } else {
699 bp = (struct pginfo *)imalloc(l);
700 if (!bp) {
701 ifree(pp);
702 return 0;
242 } 703 }
243 op = (union overhead *)sbrk(amt); 704 }
244 /* no more room! */ 705
245 if ((long)op == -1) 706 /* memory protect the page allocated in the malloc(0) case */
246 return; 707 if (bits == 0) {
247 /* 708
248 * Add new memory allocated to that on 709 bp->size = 0;
249 * free list for this hash bucket. 710 bp->shift = 1;
250 */ 711 i = malloc_minsize-1;
251 nextf[bucket] = op; 712 while (i >>= 1)
252 while (--nblks > 0) { 713 bp->shift++;
253 op->ov_next = (union overhead *)((caddr_t)op + sz); 714 bp->total = bp->free = malloc_pagesize >> bp->shift;
254 op = (union overhead *)((caddr_t)op + sz); 715 bp->page = pp;
255 } 716
717 k = mprotect(pp, malloc_pagesize, PROT_NONE);
718 if (k < 0) {
719 ifree(pp);
720 ifree(bp);
721 return 0;
722 }
723 } else {
724 bp->size = (1UL<<bits);
725 bp->shift = bits;
726 bp->total = bp->free = malloc_pagesize >> bits;
727 bp->page = pp;
728 }
729
730 /* set all valid bits in the bitmap */
731 k = bp->total;
732 i = 0;
733
734 /* Do a bunch at a time */
735 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
736 bp->bits[i / MALLOC_BITS] = ~0UL;
737
738 for(; i < k; i++)
739 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
740
741 if (bp == bp->page) {
742 /* Mark the ones we stole for ourselves */
743 for(i=0;l > 0;i++) {
744 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
745 bp->free--;
746 bp->total--;
747 l -= (1 << bits);
748 }
749 }
750
751 /* MALLOC_LOCK */
752
753 page_dir[ptr2index(pp)] = bp;
754
755 bp->next = page_dir[bits];
756 page_dir[bits] = bp;
757
758 /* MALLOC_UNLOCK */
759
760 return 1;
256} 761}
257 762
258void 763/*
259free(cp) 764 * Allocate a fragment
260 void *cp; 765 */
261{ 766static void *
262 register long size; 767malloc_bytes(size)
263 register union overhead *op; 768 size_t size;
264 769{
265 if (cp == NULL) 770 int i,j;
266 return; 771 u_long u;
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 772 struct pginfo *bp;
268#ifdef DEBUG 773 int k;
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 774 u_long *lp;
270#else 775
271 if (op->ov_magic != MAGIC) 776 /* Don't bother with anything less than this */
272 return; /* sanity */ 777 /* unless we have a malloc(0) requests */
273#endif 778 if (size != 0 && size < malloc_minsize)
274#ifdef RCHECK 779 size = malloc_minsize;
275 ASSERT(op->ov_rmagic == RMAGIC); 780
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 781 /* Find the right bucket */
277#endif 782 if (size == 0)
278 size = op->ov_index; 783 j=0;
279 ASSERT(size < NBUCKETS); 784 else {
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 785 j = 1;
281 nextf[size] = op; 786 i = size-1;
282#ifdef MSTATS 787 while (i >>= 1)
283 nmalloc[size]--; 788 j++;
284#endif 789 }
790
791 /* If it's empty, make a page more of that size chunks */
792 if (!page_dir[j] && !malloc_make_chunks(j))
793 return 0;
794
795 bp = page_dir[j];
796
797 /* Find first word of bitmap which isn't empty */
798 for (lp = bp->bits; !*lp; lp++)
799 ;
800
801 /* Find that bit, and tweak it */
802 u = 1;
803 k = 0;
804 while (!(*lp & u)) {
805 u += u;
806 k++;
807 }
808 *lp ^= u;
809
810 /* If there are no more free, remove from free-list */
811 if (!--bp->free) {
812 page_dir[j] = bp->next;
813 bp->next = 0;
814 }
815
816 /* Adjust to the real offset of that chunk */
817 k += (lp-bp->bits)*MALLOC_BITS;
818 k <<= bp->shift;
819
820 if (malloc_junk && bp->size != 0)
821 memset((char *)bp->page + k, SOME_JUNK, bp->size);
822
823 return (u_char *)bp->page + k;
285} 824}
286 825
287/* 826/*
288 * When a program attempts "storage compaction" as mentioned in the 827 * Allocate a piece of memory
289 * old malloc man page, it realloc's an already freed block. Usually
290 * this is the last block it freed; occasionally it might be farther
291 * back. We have to search all the free lists for the block in order
292 * to determine its bucket: 1st we make one pass thru the lists
293 * checking only the first block in each; if that fails we search
294 * ``realloc_srchlen'' blocks in each list for a match (the variable
295 * is extern so the caller can modify it). If that fails we just copy
296 * however many bytes was given to realloc() and hope it's not huge.
297 */ 828 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 829static void *
830imalloc(size)
831 size_t size;
832{
833 void *result;
299 834
300void * 835 if (!malloc_started)
301realloc(cp, nbytes) 836 malloc_init();
302 void *cp; 837
303 size_t nbytes; 838 if (suicide)
304{ 839 abort();
305 register u_long onb; 840
306 register long i; 841 if ((size + malloc_pagesize) < size) /* Check for overflow */
307 union overhead *op; 842 result = 0;
308 char *res; 843 else if (size <= malloc_maxsize)
309 int was_alloced = 0; 844 result = malloc_bytes(size);
310 845 else
311 if (cp == NULL) 846 result = malloc_pages(size);
312 return (malloc(nbytes)); 847
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 848 if (malloc_abort && !result)
314 if (op->ov_magic == MAGIC) { 849 wrterror("allocation failed.\n");
315 was_alloced++; 850
316 i = op->ov_index; 851 if (malloc_zero && result)
317 } else { 852 memset(result, 0, size);
318 /* 853
319 * Already free, doing "compaction". 854 return result;
320 * 855}
321 * Search for the old block of memory on the 856
322 * free list. First, check the most common 857/*
323 * case (last element free'd), then (this failing) 858 * Change the size of an allocation.
324 * the last ``realloc_srchlen'' items free'd. 859 */
325 * If all lookups fail, then assume the size of 860static void *
326 * the memory block being realloc'd is the 861irealloc(ptr, size)
327 * largest possible (so that all "nbytes" of new 862 void *ptr;
328 * memory are copied into). Note that this could cause 863 size_t size;
329 * a memory fault if the old area was tiny, and the moon 864{
330 * is gibbous. However, that is very unlikely. 865 void *p;
331 */ 866 u_long osize, index;
332 if ((i = findbucket(op, 1)) < 0 && 867 struct pginfo **mp;
333 (i = findbucket(op, realloc_srchlen)) < 0) 868 int i;
334 i = NBUCKETS; 869
870 if (suicide)
871 abort();
872
873 if (!malloc_started) {
874 wrtwarning("malloc() has never been called.\n");
875 return 0;
876 }
877
878 index = ptr2index(ptr);
879
880 if (index < malloc_pageshift) {
881 wrtwarning("junk pointer, too low to make sense.\n");
882 return 0;
883 }
884
885 if (index > last_index) {
886 wrtwarning("junk pointer, too high to make sense.\n");
887 return 0;
888 }
889
890 mp = &page_dir[index];
891
892 if (*mp == MALLOC_FIRST) { /* Page allocation */
893
894 /* Check the pointer */
895 if ((u_long)ptr & malloc_pagemask) {
896 wrtwarning("modified (page-) pointer.\n");
897 return 0;
335 } 898 }
336 onb = 1 << (i + 3); 899
337 if (onb < pagesz) 900 /* Find the size in bytes */
338 onb -= sizeof (*op) + RSLOP; 901 for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
339 else 902 osize += malloc_pagesize;
340 onb += pagesz - sizeof (*op) - RSLOP; 903
341 /* avoid the copy if same size block */ 904 if (!malloc_realloc && /* Unless we have to, */
342 if (was_alloced) { 905 size <= osize && /* .. or are too small, */
343 if (i) { 906 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
344 i = 1 << (i + 2); 907 if (malloc_junk)
345 if (i < pagesz) 908 memset((char *)ptr + size, SOME_JUNK, osize-size);
346 i -= sizeof (*op) + RSLOP; 909 return ptr; /* ..don't do anything else. */
347 else 910 }
348 i += pagesz - sizeof (*op) - RSLOP; 911
349 } 912 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
350 if (nbytes <= onb && nbytes > i) { 913
351#ifdef RCHECK 914 /* Check the pointer for sane values */
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 915 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 916 wrtwarning("modified (chunk-) pointer.\n");
354#endif 917 return 0;
355 return(cp); 918 }
356 } else 919
357 free(cp); 920 /* Find the chunk index in the page */
921 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
922
923 /* Verify that it isn't a free chunk already */
924 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
925 wrtwarning("chunk is already free.\n");
926 return 0;
927 }
928
929 osize = (*mp)->size;
930
931 if (!malloc_realloc && /* Unless we have to, */
932 size <= osize && /* ..or are too small, */
933 (size > osize/2 || /* ..or could use a smaller size, */
934 osize == malloc_minsize)) { /* ..(if there is one) */
935 if (malloc_junk)
936 memset((char *)ptr + size, SOME_JUNK, osize-size);
937 return ptr; /* ..don't do anything else. */
938 }
939
940 } else {
941 wrtwarning("pointer to wrong page.\n");
942 return 0;
943 }
944
945 p = imalloc(size);
946
947 if (p) {
948 /* copy the lesser of the two sizes, and free the old one */
949 /* Don't move from/to 0 sized region !!! */
950 if (osize != 0 && size != 0) {
951 if (osize < size)
952 memcpy(p, ptr, osize);
953 else
954 memcpy(p, ptr, size);
358 } 955 }
359 if ((res = malloc(nbytes)) == NULL) 956 ifree(ptr);
360 return (NULL); 957 }
361 if (cp != res) /* common optimization if "compacting" */ 958 return p;
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
363 return (res);
364} 959}
365 960
366/* 961/*
367 * Search ``srchlen'' elements of each free list for a block whose 962 * Free a sequence of pages
368 * header starts at ``freep''. If srchlen is -1 search the whole list.
369 * Return bucket number, or -1 if not found.
370 */ 963 */
371static 964
372findbucket(freep, srchlen) 965static __inline__ void
373 union overhead *freep; 966free_pages(ptr, index, info)
374 int srchlen; 967 void *ptr;
968 int index;
969 struct pginfo *info;
375{ 970{
376 register union overhead *p; 971 int i;
377 register int i, j; 972 struct pgfree *pf, *pt=0;
378 973 u_long l;
379 for (i = 0; i < NBUCKETS; i++) { 974 void *tail;
380 j = 0; 975
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 976 if (info == MALLOC_FREE) {
382 if (p == freep) 977 wrtwarning("page is already free.\n");
383 return (i); 978 return;
384 j++; 979 }
385 } 980
981 if (info != MALLOC_FIRST) {
982 wrtwarning("pointer to wrong page.\n");
983 return;
984 }
985
986 if ((u_long)ptr & malloc_pagemask) {
987 wrtwarning("modified (page-) pointer.\n");
988 return;
989 }
990
991 /* Count how many pages and mark them free at the same time */
992 page_dir[index] = MALLOC_FREE;
993 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
994 page_dir[index + i] = MALLOC_FREE;
995
996 l = i << malloc_pageshift;
997
998 if (malloc_junk)
999 memset(ptr, SOME_JUNK, l);
1000
1001#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1002 if (malloc_hint)
1003 madvise(ptr, l, MADV_FREE);
1004#endif
1005
1006 tail = (char *)ptr+l;
1007
1008 /* add to free-list */
1009 if (!px)
1010 px = imalloc(sizeof *px); /* This cannot fail... */
1011 px->page = ptr;
1012 px->end = tail;
1013 px->size = l;
1014 if (!free_list.next) {
1015
1016 /* Nothing on free list, put this at head */
1017 px->next = free_list.next;
1018 px->prev = &free_list;
1019 free_list.next = px;
1020 pf = px;
1021 px = 0;
1022
1023 } else {
1024
1025 /* Find the right spot, leave pf pointing to the modified entry. */
1026 tail = (char *)ptr+l;
1027
1028 for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next)
1029 ; /* Race ahead here */
1030
1031 if (pf->page > tail) {
1032 /* Insert before entry */
1033 px->next = pf;
1034 px->prev = pf->prev;
1035 pf->prev = px;
1036 px->prev->next = px;
1037 pf = px;
1038 px = 0;
1039 } else if (pf->end == ptr ) {
1040 /* Append to the previous entry */
1041 pf->end = (char *)pf->end + l;
1042 pf->size += l;
1043 if (pf->next && pf->end == pf->next->page ) {
1044 /* And collapse the next too. */
1045 pt = pf->next;
1046 pf->end = pt->end;
1047 pf->size += pt->size;
1048 pf->next = pt->next;
1049 if (pf->next)
1050 pf->next->prev = pf;
1051 }
1052 } else if (pf->page == tail) {
1053 /* Prepend to entry */
1054 pf->size += l;
1055 pf->page = ptr;
1056 } else if (!pf->next) {
1057 /* Append at tail of chain */
1058 px->next = 0;
1059 px->prev = pf;
1060 pf->next = px;
1061 pf = px;
1062 px = 0;
1063 } else {
1064 wrterror("freelist is destroyed.\n");
386 } 1065 }
387 return (-1); 1066 }
1067
1068 /* Return something to OS ? */
1069 if (!pf->next && /* If we're the last one, */
1070 pf->size > malloc_cache && /* ..and the cache is full, */
1071 pf->end == malloc_brk && /* ..and none behind us, */
1072 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1073
1074 /*
1075 * Keep the cache intact. Notice that the '>' above guarantees that
1076 * the pf will always have at least one page afterwards.
1077 */
1078 pf->end = (char *)pf->page + malloc_cache;
1079 pf->size = malloc_cache;
1080
1081 brk(pf->end);
1082 malloc_brk = pf->end;
1083
1084 index = ptr2index(pf->end);
1085
1086 for(i=index;i <= last_index;)
1087 page_dir[i++] = MALLOC_NOT_MINE;
1088
1089 last_index = index - 1;
1090
1091 /* XXX: We could realloc/shrink the pagedir here I guess. */
1092 }
1093 if (pt)
1094 ifree(pt);
388} 1095}
389 1096
390#ifdef MSTATS
391/* 1097/*
392 * mstats - print out statistics about malloc 1098 * Free a chunk, and possibly the page it's on, if the page becomes empty.
393 *
394 * Prints two lines of numbers, one showing the length of the free list
395 * for each size category, the second showing the number of mallocs -
396 * frees for each size category.
397 */ 1099 */
398mstats(s) 1100
399 char *s; 1101/* ARGSUSED */
1102static __inline__ void
1103free_bytes(ptr, index, info)
1104 void *ptr;
1105 int index;
1106 struct pginfo *info;
400{ 1107{
401 register int i, j; 1108 int i;
402 register union overhead *p; 1109 struct pginfo **mp;
403 int totfree = 0, 1110 void *vp;
404 totused = 0; 1111
405 1112 /* Find the chunk number on the page */
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1113 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
407 for (i = 0; i < NBUCKETS; i++) { 1114
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1115 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
409 ; 1116 wrtwarning("modified (chunk-) pointer.\n");
410 fprintf(stderr, " %d", j); 1117 return;
411 totfree += j * (1 << (i + 3)); 1118 }
412 } 1119
413 fprintf(stderr, "\nused:\t"); 1120 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
414 for (i = 0; i < NBUCKETS; i++) { 1121 wrtwarning("chunk is already free.\n");
415 fprintf(stderr, " %d", nmalloc[i]); 1122 return;
416 totused += nmalloc[i] * (1 << (i + 3)); 1123 }
417 } 1124
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1125 if (malloc_junk && info->size != 0)
419 totused, totfree); 1126 memset(ptr, SOME_JUNK, info->size);
1127
1128 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1129 info->free++;
1130
1131 if (info->size != 0)
1132 mp = page_dir + info->shift;
1133 else
1134 mp = page_dir;
1135
1136 if (info->free == 1) {
1137
1138 /* Page became non-full */
1139
1140 /* Insert in address order */
1141 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1142 mp = &(*mp)->next;
1143 info->next = *mp;
1144 *mp = info;
1145 return;
1146 }
1147
1148 if (info->free != info->total)
1149 return;
1150
1151 /* Find & remove this page in the queue */
1152 while (*mp != info) {
1153 mp = &((*mp)->next);
1154#ifdef MALLOC_EXTRA_SANITY
1155 if (!*mp)
1156 wrterror("(ES): Not on queue\n");
1157#endif /* MALLOC_EXTRA_SANITY */
1158 }
1159 *mp = info->next;
1160
1161 /* Free the page & the info structure if need be */
1162 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1163
1164 /* If the page was mprotected, unprotect it before releasing it */
1165 if (info->size == 0) {
1166 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1167 /* Do we have to care if mprotect succeeds here ? */
1168 }
1169
1170 vp = info->page; /* Order is important ! */
1171 if(vp != (void*)info)
1172 ifree(info);
1173 ifree(vp);
1174}
1175
1176static void
1177ifree(ptr)
1178 void *ptr;
1179{
1180 struct pginfo *info;
1181 int index;
1182
1183 /* This is legal */
1184 if (!ptr)
1185 return;
1186
1187 if (!malloc_started) {
1188 wrtwarning("malloc() has never been called.\n");
1189 return;
1190 }
1191
1192 /* If we're already sinking, don't make matters any worse. */
1193 if (suicide)
1194 return;
1195
1196 index = ptr2index(ptr);
1197
1198 if (index < malloc_pageshift) {
1199 wrtwarning("junk pointer, too low to make sense.\n");
1200 return;
1201 }
1202
1203 if (index > last_index) {
1204 wrtwarning("junk pointer, too high to make sense.\n");
1205 return;
1206 }
1207
1208 info = page_dir[index];
1209
1210 if (info < MALLOC_MAGIC)
1211 free_pages(ptr, index, info);
1212 else
1213 free_bytes(ptr, index, info);
1214 return;
1215}
1216
1217/*
1218 * These are the public exported interface routines.
1219 */
1220
1221static int malloc_active;
1222
1223void *
1224malloc(size_t size)
1225{
1226 register void *r;
1227
1228 malloc_func = " in malloc():";
1229 _MALLOC_LOCK();
1230 if (malloc_active++) {
1231 wrtwarning("recursive call.\n");
1232 malloc_active--;
1233 _MALLOC_UNLOCK();
1234 return (0);
1235 }
1236 r = imalloc(size);
1237 UTRACE(0, size, r);
1238 malloc_active--;
1239 _MALLOC_UNLOCK();
1240 if (malloc_xmalloc && !r)
1241 wrterror("out of memory.\n");
1242 return (r);
1243}
1244
1245void
1246free(void *ptr)
1247{
1248 malloc_func = " in free():";
1249 _MALLOC_LOCK();
1250 if (malloc_active++) {
1251 wrtwarning("recursive call.\n");
1252 malloc_active--;
1253 _MALLOC_UNLOCK();
1254 return;
1255 }
1256 ifree(ptr);
1257 UTRACE(ptr, 0, 0);
1258 malloc_active--;
1259 _MALLOC_UNLOCK();
1260 return;
1261}
1262
1263void *
1264realloc(void *ptr, size_t size)
1265{
1266 register void *r;
1267
1268 malloc_func = " in realloc():";
1269 _MALLOC_LOCK();
1270 if (malloc_active++) {
1271 wrtwarning("recursive call.\n");
1272 malloc_active--;
1273 _MALLOC_UNLOCK();
1274 return (0);
1275 }
1276 if (!ptr) {
1277 r = imalloc(size);
1278 } else {
1279 r = irealloc(ptr, size);
1280 }
1281 UTRACE(ptr, size, r);
1282 malloc_active--;
1283 _MALLOC_UNLOCK();
1284 if (malloc_xmalloc && !r)
1285 wrterror("out of memory.\n");
1286 return (r);
420} 1287}
421#endif
diff --git a/src/lib/libc/stdlib/memory.3 b/src/lib/libc/stdlib/memory.3
index 735252c837..959a173a03 100644
--- a/src/lib/libc/stdlib/memory.3
+++ b/src/lib/libc/stdlib/memory.3
@@ -29,12 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)memory.3 5.1 (Berkeley) 5/2/91 32.\" $OpenBSD: memory.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
33.\" $Id: memory.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd May 2, 1991
36.Dt MEMORY 3 35.Dt MEMORY 3
37.Os BSD 4 36.Os
38.Sh NAME 37.Sh NAME
39.Nm malloc , 38.Nm malloc ,
40.Nm free , 39.Nm free ,
@@ -56,16 +55,15 @@
56.Fn alloca "size_t size" 55.Fn alloca "size_t size"
57.Sh DESCRIPTION 56.Sh DESCRIPTION
58These functions allocate and free memory for the calling process. 57These functions allocate and free memory for the calling process.
59They are described in the 58They are described in the individual man pages.
60individual manual pages.
61.Sh SEE ALSO 59.Sh SEE ALSO
60.Xr alloca 3 ,
62.Xr calloc 3 , 61.Xr calloc 3 ,
63.Xr free 3 , 62.Xr free 3 ,
64.Xr malloc 3 , 63.Xr malloc 3 ,
65.Xr realloc 3 , 64.Xr realloc 3
66.Xr alloca 3 ,
67.Sh STANDARDS 65.Sh STANDARDS
68These functions, with the exception of 66These functions, with the exception of
69.Fn alloca 67.Fn alloca ,
70conform to 68conform to
71.St -ansiC . 69.St -ansiC .
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
index 381fdc0830..4ae6488af2 100644
--- a/src/lib/libc/stdlib/merge.c
+++ b/src/lib/libc/stdlib/merge.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)merge.c 8.2 (Berkeley) 2/14/94";*/ 38static char *rcsid = "$OpenBSD: merge.c,v 1.5 2002/02/17 19:42:24 millert Exp $";
39static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42/* 41/*
@@ -59,8 +58,8 @@ static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
59#include <stdlib.h> 58#include <stdlib.h>
60#include <string.h> 59#include <string.h>
61 60
62static void setup __P((u_char *, u_char *, size_t, size_t, int (*)())); 61static void setup(u_char *, u_char *, size_t, size_t, int (*)());
63static void insertionsort __P((u_char *, size_t, size_t, int (*)())); 62static void insertionsort(u_char *, size_t, size_t, int (*)());
64 63
65#define ISIZE sizeof(int) 64#define ISIZE sizeof(int)
66#define PSIZE sizeof(u_char *) 65#define PSIZE sizeof(u_char *)
@@ -100,7 +99,7 @@ mergesort(base, nmemb, size, cmp)
100 void *base; 99 void *base;
101 size_t nmemb; 100 size_t nmemb;
102 register size_t size; 101 register size_t size;
103 int (*cmp) __P((const void *, const void *)); 102 int (*cmp)(const void *, const void *);
104{ 103{
105 register int i, sense; 104 register int i, sense;
106 int big, iflag; 105 int big, iflag;
@@ -148,7 +147,7 @@ mergesort(base, nmemb, size, cmp)
148 sense = 0; 147 sense = 0;
149 } 148 }
150 if (!big) { /* here i = 0 */ 149 if (!big) { /* here i = 0 */
151LINEAR: while ((b += size) < t && cmp(q, b) >sense) 150 while ((b += size) < t && cmp(q, b) >sense)
152 if (++i == 6) { 151 if (++i == 6) {
153 big = 1; 152 big = 1;
154 goto EXPONENTIAL; 153 goto EXPONENTIAL;
@@ -169,7 +168,7 @@ EXPONENTIAL: for (i = size; ; i <<= 1)
169 goto FASTCASE; 168 goto FASTCASE;
170 } else 169 } else
171 b = p; 170 b = p;
172SLOWCASE: while (t > b+size) { 171 while (t > b+size) {
173 i = (((t - b) / size) >> 1) * size; 172 i = (((t - b) / size) >> 1) * size;
174 if ((*cmp)(q, p = b + i) <= sense) 173 if ((*cmp)(q, p = b + i) <= sense)
175 t = p; 174 t = p;
@@ -258,7 +257,7 @@ COPY: b = t;
258void 257void
259setup(list1, list2, n, size, cmp) 258setup(list1, list2, n, size, cmp)
260 size_t n, size; 259 size_t n, size;
261 int (*cmp) __P((const void *, const void *)); 260 int (*cmp)(const void *, const void *);
262 u_char *list1, *list2; 261 u_char *list1, *list2;
263{ 262{
264 int i, length, size2, tmp, sense; 263 int i, length, size2, tmp, sense;
@@ -333,7 +332,7 @@ static void
333insertionsort(a, n, size, cmp) 332insertionsort(a, n, size, cmp)
334 u_char *a; 333 u_char *a;
335 size_t n, size; 334 size_t n, size;
336 int (*cmp) __P((const void *, const void *)); 335 int (*cmp)(const void *, const void *);
337{ 336{
338 u_char *ai, *s, *t, *u, tmp; 337 u_char *ai, *s, *t, *u, tmp;
339 int i; 338 int i;
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
index 43356e66b3..cd34260b5c 100644
--- a/src/lib/libc/stdlib/mrand48.c
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: mrand48.c,v 1.2 1996/08/19 08:33:39 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/multibyte.c b/src/lib/libc/stdlib/multibyte.c
index fe1cd5781b..6f08bbe342 100644
--- a/src/lib/libc/stdlib/multibyte.c
+++ b/src/lib/libc/stdlib/multibyte.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)multibyte.c 5.1 (Berkeley) 2/18/91";*/ 35static char *rcsid = "$OpenBSD: multibyte.c,v 1.3 2002/02/19 19:39:37 millert Exp $";
36static char *rcsid = "$Id: multibyte.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -74,13 +73,7 @@ mbtowc(pwc, s, n)
74 73
75/*ARGSUSED*/ 74/*ARGSUSED*/
76int 75int
77#ifdef __STDC__
78wctomb(char *s, wchar_t wchar) 76wctomb(char *s, wchar_t wchar)
79#else
80wctomb(s, wchar)
81 char *s;
82 wchar_t wchar;
83#endif
84{ 77{
85 if (s == NULL) 78 if (s == NULL)
86 return 0; 79 return 0;
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
index 63f839cb05..b1ec2cebb1 100644
--- a/src/lib/libc/stdlib/nrand48.c
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: nrand48.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16long 20long
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c
index 2194c2c608..d8c4886d4b 100644
--- a/src/lib/libc/stdlib/putenv.c
+++ b/src/lib/libc/stdlib/putenv.c
@@ -1,6 +1,6 @@
1/*- 1/*-
2 * Copyright (c) 1988 The Regents of the University of California. 2 * Copyright (c) 1988, 1993
3 * All rights reserved. 3 * The Regents of the University of California. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)putenv.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: putenv.c,v 1.2 1996/08/10 05:03:00 tholo Exp $";
36static char *rcsid = "$Id: putenv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -43,17 +42,17 @@ int
43putenv(str) 42putenv(str)
44 const char *str; 43 const char *str;
45{ 44{
46 register char *p, *equal; 45 char *p, *equal;
47 int rval; 46 int rval;
48 47
49 if (!(p = strdup(str))) 48 if ((p = strdup(str)) == NULL)
50 return(1); 49 return (-1);
51 if (!(equal = strchr(p, '='))) { 50 if ((equal = strchr(p, '=')) == NULL) {
52 (void)free(p); 51 (void)free(p);
53 return(1); 52 return (-1);
54 } 53 }
55 *equal = '\0'; 54 *equal = '\0';
56 rval = setenv(p, equal + 1, 1); 55 rval = setenv(p, equal + 1, 1);
57 (void)free(p); 56 (void)free(p);
58 return(rval); 57 return (rval);
59} 58}
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
index cb1e052191..ef0307ab25 100644
--- a/src/lib/libc/stdlib/qabs.3
+++ b/src/lib/libc/stdlib/qabs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: qabs.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: qabs.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt QABS 3 39.Dt QABS 3
@@ -49,14 +48,13 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn qabs 50.Fn qabs
52function 51function returns the absolute value of the quad integer
53returns the absolute value of the quad integer 52.Fa j .
54.Ar j .
55.Sh SEE ALSO 53.Sh SEE ALSO
56.Xr abs 3 , 54.Xr abs 3 ,
57.Xr labs 3 ,
58.Xr floor 3 ,
59.Xr cabs 3 , 55.Xr cabs 3 ,
56.Xr floor 3 ,
57.Xr labs 3 ,
60.Xr math 3 58.Xr math 3
61.Sh BUGS 59.Sh BUGS
62The absolute value of the most negative integer remains negative. 60The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/qabs.c b/src/lib/libc/stdlib/qabs.c
index 9c51a8baa9..ccc42cbec6 100644
--- a/src/lib/libc/stdlib/qabs.c
+++ b/src/lib/libc/stdlib/qabs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: qabs.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
36static char *rcsid = "$Id: qabs.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
index 0efcfc96ef..4db47d9b4a 100644
--- a/src/lib/libc/stdlib/qdiv.3
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)qdiv.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: qdiv.3,v 1.4 2000/12/24 00:31:00 aaron Exp $
37.\" $Id: qdiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt QDIV 3 39.Dt QDIV 3
@@ -49,17 +48,16 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn qdiv 50.Fn qdiv
52function 51function computes the value
53computes the value 52.Fa num Ns No / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 53and returns the quotient and remainder in a structure named
56.Ar qdiv_t 54.Li qdiv_t
57that contains two 55that contains two
58.Em quad integer 56.Li quad integer
59members named 57members named
60.Ar quot 58.Fa quot
61and 59and
62.Ar rem . 60.Fa rem .
63.Sh SEE ALSO 61.Sh SEE ALSO
64.Xr div 3 , 62.Xr div 3 ,
65.Xr ldiv 3 , 63.Xr ldiv 3 ,
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
index 8f8e3f89c4..07e84cd649 100644
--- a/src/lib/libc/stdlib/qdiv.c
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: qdiv.c,v 1.2 1996/08/19 08:33:41 tholo Exp $";
39static char *rcsid = "$Id: qdiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* qdiv_t */ 41#include <stdlib.h> /* qdiv_t */
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
index eb122cde12..a0561cadbe 100644
--- a/src/lib/libc/stdlib/qsort.3
+++ b/src/lib/libc/stdlib/qsort.3
@@ -33,14 +33,15 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)qsort.3 8.1 (Berkeley) 6/4/93 36.\" $OpenBSD: qsort.3,v 1.10 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: qsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 4, 1993 38.Dd June 4, 1993
40.Dt QSORT 3 39.Dt QSORT 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm qsort, heapsort, mergesort 42.Nm qsort ,
43.Nm heapsort ,
44.Nm mergesort
44.Nd sort functions 45.Nd sort functions
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
@@ -72,7 +73,7 @@ objects, the initial member of which is pointed to by
72.Fa base . 73.Fa base .
73The size of each object is specified by 74The size of each object is specified by
74.Fa size . 75.Fa size .
75.Fn Mergesort 76.Fn mergesort
76behaves similarly, but 77behaves similarly, but
77.Em requires 78.Em requires
78that 79that
@@ -106,51 +107,49 @@ is stable.
106.Pp 107.Pp
107The 108The
108.Fn qsort 109.Fn qsort
109function is an implementation of C.A.R. Hoare's ``quicksort'' algorithm, 110function is an implementation of C.A.R. Hoare's
111.Dq quicksort
112algorithm,
110a variant of partition-exchange sorting; in particular, see D.E. Knuth's 113a variant of partition-exchange sorting; in particular, see D.E. Knuth's
111Algorithm Q. 114Algorithm Q.
112.Fn Qsort 115.Fn qsort
113takes O N lg N average time. 116takes O N lg N average time.
114This implementation uses median selection to avoid its 117This implementation uses median selection to avoid its
115O N**2 worst-case behavior. 118O N**2 worst-case behavior.
116.Pp 119.Pp
117The 120The
118.Fn heapsort 121.Fn heapsort
119function is an implementation of J.W.J. William's ``heapsort'' algorithm, 122function is an implementation of J.W.J. William's
123.Dq heapsort
124algorithm,
120a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H. 125a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
121.Fn Heapsort 126.Fn heapsort
122takes O N lg N worst-case time. 127takes O N lg N worst-case time.
123Its 128This implementation of
124.Em only
125advantage over
126.Fn qsort 129.Fn qsort
127is that it uses almost no additional memory; while 130is implemented without recursive function calls.
128.Fn qsort
129does not allocate memory, it is implemented using recursion.
130.Pp 131.Pp
131The function 132The function
132.Fn mergesort 133.Fn mergesort
133requires additional memory of size 134requires additional memory of size
134.Fa nmemb * 135.Fa nmemb *
135.Fa size 136.Fa size
136bytes; it should be used only when space is not at a premium. 137bytes; it should be used only when space is not at a premium.
137.Fn Mergesort 138.Fn mergesort
138is optimized for data with pre-existing order; its worst case 139is optimized for data with pre-existing order; its worst case
139time is O N lg N; its best case is O N. 140time is O N lg N; its best case is O N.
140.Pp 141.Pp
141Normally, 142Normally,
142.Fn qsort 143.Fn qsort
143is faster than 144is faster than
144.Fn mergesort 145.Fn mergesort ,
145is faster than 146which is faster than
146.Fn heapsort . 147.Fn heapsort .
147Memory availability and pre-existing order in the data can make this 148Memory availability and pre-existing order in the data can make this untrue.
148untrue.
149.Sh RETURN VALUES 149.Sh RETURN VALUES
150The 150The
151.Fn qsort 151.Fn qsort
152function 152function returns no value.
153returns no value.
154.Pp 153.Pp
155Upon successful completion, 154Upon successful completion,
156.Fn heapsort 155.Fn heapsort
@@ -163,20 +162,21 @@ is set to indicate the error.
163.Sh ERRORS 162.Sh ERRORS
164The 163The
165.Fn heapsort 164.Fn heapsort
166function succeeds unless: 165and
166.Fn mergesort
167functions succeed unless:
167.Bl -tag -width Er 168.Bl -tag -width Er
168.It Bq Er EINVAL 169.It Bq Er EINVAL
169The 170The
170.Fa size 171.Fa size
171argument is zero, or, 172argument is zero, or the
172the
173.Fa size 173.Fa size
174argument to 174argument to
175.Fn mergesort 175.Fn mergesort
176is less than 176is less than
177.Dq "sizeof(void *) / 2" . 177.Dq "sizeof(void *) / 2" .
178.It Bq Er ENOMEM 178.It Bq Er ENOMEM
179.Fn Heapsort 179.Fn heapsort
180or 180or
181.Fn mergesort 181.Fn mergesort
182were unable to allocate memory. 182were unable to allocate memory.
@@ -185,7 +185,7 @@ were unable to allocate memory.
185Previous versions of 185Previous versions of
186.Fn qsort 186.Fn qsort
187did not permit the comparison routine itself to call 187did not permit the comparison routine itself to call
188.Fn qsort 3 . 188.Fn qsort .
189This is no longer true. 189This is no longer true.
190.Sh SEE ALSO 190.Sh SEE ALSO
191.Xr sort 1 , 191.Xr sort 1 ,
@@ -229,6 +229,5 @@ This is no longer true.
229.Sh STANDARDS 229.Sh STANDARDS
230The 230The
231.Fn qsort 231.Fn qsort
232function 232function conforms to
233conforms to
234.St -ansiC . 233.St -ansiC .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
index c06bd54054..9b8bb5801b 100644
--- a/src/lib/libc/stdlib/qsort.c
+++ b/src/lib/libc/stdlib/qsort.c
@@ -32,15 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char sccsid[] = "from: @(#)qsort.c 8.1 (Berkeley) 6/4/93";*/ 35static char *rcsid = "$OpenBSD: qsort.c,v 1.7 2002/02/17 19:42:24 millert Exp $";
36static char *rcsid = "$Id: qsort.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
40#include <stdlib.h> 39#include <stdlib.h>
41 40
42static inline char *med3 __P((char *, char *, char *, int (*)())); 41static __inline char *med3(char *, char *, char *, int (*)());
43static inline void swapfunc __P((char *, char *, int, int)); 42static __inline void swapfunc(char *, char *, int, int);
44 43
45#define min(a, b) (a) < (b) ? a : b 44#define min(a, b) (a) < (b) ? a : b
46 45
@@ -61,12 +60,12 @@ static inline void swapfunc __P((char *, char *, int, int));
61#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 60#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
62 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 61 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
63 62
64static inline void 63static __inline void
65swapfunc(a, b, n, swaptype) 64swapfunc(a, b, n, swaptype)
66 char *a, *b; 65 char *a, *b;
67 int n, swaptype; 66 int n, swaptype;
68{ 67{
69 if(swaptype <= 1) 68 if (swaptype <= 1)
70 swapcode(long, a, b, n) 69 swapcode(long, a, b, n)
71 else 70 else
72 swapcode(char, a, b, n) 71 swapcode(char, a, b, n)
@@ -82,7 +81,7 @@ swapfunc(a, b, n, swaptype)
82 81
83#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 82#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
84 83
85static inline char * 84static __inline char *
86med3(a, b, c, cmp) 85med3(a, b, c, cmp)
87 char *a, *b, *c; 86 char *a, *b, *c;
88 int (*cmp)(); 87 int (*cmp)();
@@ -93,27 +92,28 @@ med3(a, b, c, cmp)
93} 92}
94 93
95void 94void
96qsort(a, n, es, cmp) 95qsort(aa, n, es, cmp)
97 void *a; 96 void *aa;
98 size_t n, es; 97 size_t n, es;
99 int (*cmp)(); 98 int (*cmp)();
100{ 99{
101 char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 100 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
102 int d, r, swaptype, swap_cnt; 101 int d, r, swaptype, swap_cnt;
102 register char *a = aa;
103 103
104loop: SWAPINIT(a, es); 104loop: SWAPINIT(a, es);
105 swap_cnt = 0; 105 swap_cnt = 0;
106 if (n < 7) { 106 if (n < 7) {
107 for (pm = a + es; pm < (char *) a + n * es; pm += es) 107 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
108 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 108 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
109 pl -= es) 109 pl -= es)
110 swap(pl, pl - es); 110 swap(pl, pl - es);
111 return; 111 return;
112 } 112 }
113 pm = a + (n / 2) * es; 113 pm = (char *)a + (n / 2) * es;
114 if (n > 7) { 114 if (n > 7) {
115 pl = a; 115 pl = (char *)a;
116 pn = a + (n - 1) * es; 116 pn = (char *)a + (n - 1) * es;
117 if (n > 40) { 117 if (n > 40) {
118 d = (n / 8) * es; 118 d = (n / 8) * es;
119 pl = med3(pl, pl + d, pl + 2 * d, cmp); 119 pl = med3(pl, pl + d, pl + 2 * d, cmp);
@@ -123,9 +123,9 @@ loop: SWAPINIT(a, es);
123 pm = med3(pl, pm, pn, cmp); 123 pm = med3(pl, pm, pn, cmp);
124 } 124 }
125 swap(a, pm); 125 swap(a, pm);
126 pa = pb = a + es; 126 pa = pb = (char *)a + es;
127 127
128 pc = pd = a + (n - 1) * es; 128 pc = pd = (char *)a + (n - 1) * es;
129 for (;;) { 129 for (;;) {
130 while (pb <= pc && (r = cmp(pb, a)) <= 0) { 130 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
131 if (r == 0) { 131 if (r == 0) {
@@ -151,14 +151,14 @@ loop: SWAPINIT(a, es);
151 pc -= es; 151 pc -= es;
152 } 152 }
153 if (swap_cnt == 0) { /* Switch to insertion sort */ 153 if (swap_cnt == 0) { /* Switch to insertion sort */
154 for (pm = a + es; pm < (char *) a + n * es; pm += es) 154 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
155 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 155 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
156 pl -= es) 156 pl -= es)
157 swap(pl, pl - es); 157 swap(pl, pl - es);
158 return; 158 return;
159 } 159 }
160 160
161 pn = a + n * es; 161 pn = (char *)a + n * es;
162 r = min(pa - (char *)a, pb - pa); 162 r = min(pa - (char *)a, pb - pa);
163 vecswap(a, pb - r, r); 163 vecswap(a, pb - r, r);
164 r = min(pd - pc, pn - pd - es); 164 r = min(pd - pc, pn - pd - es);
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
index a2af9f17a4..f70990fa8e 100644
--- a/src/lib/libc/stdlib/radixsort.3
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -29,8 +29,7 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)radixsort.3 8.2 (Berkeley) 1/27/94 32.\" $OpenBSD: radixsort.3,v 1.7 2001/08/06 10:42:26 mpech Exp $
33.\" $Id: radixsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 33.\"
35.Dd January 27, 1994 34.Dd January 27, 1994
36.Dt RADIXSORT 3 35.Dt RADIXSORT 3
@@ -42,16 +41,15 @@
42.Fd #include <limits.h> 41.Fd #include <limits.h>
43.Fd #include <stdlib.h> 42.Fd #include <stdlib.h>
44.Ft int 43.Ft int
45.Fn radixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 44.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
46.Ft int 45.Ft int
47.Fn sradixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 46.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
48.Sh DESCRIPTION 47.Sh DESCRIPTION
49The 48The
50.Fn radixsort 49.Fn radixsort
51and 50and
52.Fn sradixsort 51.Fn sradixsort
53functions 52functions are implementations of radix sort.
54are implementations of radix sort.
55.Pp 53.Pp
56These functions sort an array of pointers to byte strings, the initial 54These functions sort an array of pointers to byte strings, the initial
57member of which is referenced by 55member of which is referenced by
@@ -63,26 +61,24 @@ is denoted by the user-specified value
63Applications may specify a sort order by providing the 61Applications may specify a sort order by providing the
64.Fa table 62.Fa table
65argument. 63argument.
66If 64If non-null,
67.Pf non- Dv NULL ,
68.Fa table 65.Fa table
69must reference an array of 66must reference an array of
70.Dv UCHAR_MAX 67.Dv UCHAR_MAX
71+ 1 bytes which contains the sort 68+ 1 bytes which contains the sort weight of each possible byte value.
72weight of each possible byte value.
73The end-of-string byte must have a sort weight of 0 or 255 69The end-of-string byte must have a sort weight of 0 or 255
74(for sorting in reverse order). 70(for sorting in reverse order).
75More than one byte may have the same sort weight. 71More than one byte may have the same sort weight.
76The 72The
77.Fa table 73.Fa table
78argument 74argument is useful for applications which wish to sort different characters
79is useful for applications which wish to sort different characters
80equally, for example, providing a table with the same weights 75equally, for example, providing a table with the same weights
81for A-Z as for a-z will result in a case-insensitive sort. 76for A-Z as for a-z will result in a case-insensitive sort.
82If 77If
83.Fa table 78.Fa table
84is NULL, the contents of the array are sorted in ascending order 79is
85according to the 80.Dv NULL ,
81the contents of the array are sorted in ascending order according to the
86.Tn ASCII 82.Tn ASCII
87order of the byte strings they reference and 83order of the byte strings they reference and
88.Fa endbyte 84.Fa endbyte
@@ -107,7 +103,7 @@ particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
107They take linear time relative to the number of bytes in the strings. 103They take linear time relative to the number of bytes in the strings.
108.Sh RETURN VALUES 104.Sh RETURN VALUES
109Upon successful completion 0 is returned. 105Upon successful completion 0 is returned.
110Otherwise, \-1 is returned and the global variable 106Otherwise, \-1 is returned and the global variable
111.Va errno 107.Va errno
112is set to indicate the error. 108is set to indicate the error.
113.Sh ERRORS 109.Sh ERRORS
@@ -122,15 +118,13 @@ is not 0 or 255.
122.Pp 118.Pp
123Additionally, the 119Additionally, the
124.Fn sradixsort 120.Fn sradixsort
125function 121function may fail and set
126may fail and set
127.Va errno 122.Va errno
128for any of the errors specified for the library routine 123for any of the errors specified for the library routine
129.Xr malloc 3 . 124.Xr malloc 3 .
130.Sh SEE ALSO 125.Sh SEE ALSO
131.Xr sort 1 , 126.Xr sort 1 ,
132.Xr qsort 3 127.Xr qsort 3
133.Pp
134.Rs 128.Rs
135.%A Knuth, D.E. 129.%A Knuth, D.E.
136.%D 1968 130.%D 1968
@@ -158,4 +152,5 @@ for any of the errors specified for the library routine
158.Sh HISTORY 152.Sh HISTORY
159The 153The
160.Fn radixsort 154.Fn radixsort
161function first appeared in 4.4BSD. 155function first appeared in
156.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
index dd51013c94..e03b479715 100644
--- a/src/lib/libc/stdlib/radixsort.c
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)radixsort.c 8.1 (Berkeley) 6/4/93";*/ 38static char *rcsid = "$OpenBSD: radixsort.c,v 1.5 2002/02/17 19:42:24 millert Exp $";
39static char *rcsid = "$Id: radixsort.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42/* 41/*
@@ -61,11 +60,11 @@ typedef struct {
61 int sn, si; 60 int sn, si;
62} stack; 61} stack;
63 62
64static inline void simplesort 63static __inline void simplesort
65 __P((const u_char **, int, int, const u_char *, u_int)); 64(const u_char **, int, int, const u_char *, u_int);
66static void r_sort_a __P((const u_char **, int, int, const u_char *, u_int)); 65static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
67static void r_sort_b __P((const u_char **, 66static void r_sort_b(const u_char **,
68 const u_char **, int, int, const u_char *, u_int)); 67 const u_char **, int, int, const u_char *, u_int);
69 68
70#define THRESHOLD 20 /* Divert to simplesort(). */ 69#define THRESHOLD 20 /* Divert to simplesort(). */
71#define SIZE 512 /* Default stack size. */ 70#define SIZE 512 /* Default stack size. */
@@ -295,7 +294,7 @@ r_sort_b(a, ta, n, i, tr, endch)
295 } 294 }
296} 295}
297 296
298static inline void 297static __inline void
299simplesort(a, n, b, tr, endch) /* insertion sort */ 298simplesort(a, n, b, tr, endch) /* insertion sort */
300 register const u_char **a; 299 register const u_char **a;
301 int n, b; 300 int n, b;
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
index a0e7740e66..8899c2e104 100644
--- a/src/lib/libc/stdlib/rand.3
+++ b/src/lib/libc/stdlib/rand.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)rand.3 6.7 (Berkeley) 6/29/91 36.\" $OpenBSD: rand.3,v 1.8 2001/05/13 23:38:02 millert Exp $
37.\" $Id: rand.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt RAND 3 39.Dt RAND 3
@@ -46,12 +45,15 @@
46.Sh SYNOPSIS 45.Sh SYNOPSIS
47.Fd #include <stdlib.h> 46.Fd #include <stdlib.h>
48.Ft void 47.Ft void
49.Fn srand "unsigned seed" 48.Fn srand "unsigned int seed"
50.Ft int 49.Ft int
51.Fn rand void 50.Fn rand void
51.Ft int
52.Fn rand_r "unsigned int *seed"
52.Sh DESCRIPTION 53.Sh DESCRIPTION
53.Bf -symbolic 54.Bf -symbolic
54These interfaces are obsoleted by random(3). 55These interfaces are obsoleted by
56.Xr random 3 .
55.Ef 57.Ef
56.Pp 58.Pp
57The 59The
@@ -73,13 +75,28 @@ with the same seed value.
73.Pp 75.Pp
74If no seed value is provided, the functions are automatically 76If no seed value is provided, the functions are automatically
75seeded with a value of 1. 77seeded with a value of 1.
78.Pp
79The
80.Fn rand_r
81is a thread-safe version of
82.Fn rand .
83Storage for the seed must be provided through the
84.Fa seed
85argument, and needs to have been initialized by the caller.
76.Sh SEE ALSO 86.Sh SEE ALSO
87.Xr arc4random 3 ,
88.Xr rand48 3 ,
77.Xr random 3 89.Xr random 3
78.Sh STANDARDS 90.Sh STANDARDS
79The 91The
80.Fn rand 92.Fn rand
81and 93and
82.Fn srand 94.Fn srand
83functions 95functions conform to
84conform to
85.St -ansiC . 96.St -ansiC .
97.Pp
98The
99.Fn rand_r
100function conforms to ISO/IEC 9945-1 ANSI/IEEE
101.Pq Dq Tn POSIX
102Std 1003.1c Draft 10.
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
index 361d473448..bb180886c0 100644
--- a/src/lib/libc/stdlib/rand.c
+++ b/src/lib/libc/stdlib/rand.c
@@ -32,24 +32,34 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)rand.c 5.6 (Berkeley) 6/24/91";*/ 35static char *rcsid = "$OpenBSD: rand.c,v 1.6 1998/12/07 21:47:22 millert Exp $";
36static char *rcsid = "$Id: rand.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
40#include <stdlib.h> 39#include <stdlib.h>
41 40
42static u_long next = 1; 41static u_int next = 1;
42
43int
44rand_r(seed)
45u_int *seed;
46{
47
48 *seed = *seed * 1103515245 + 12345;
49 return (*seed % ((u_int)RAND_MAX + 1));
50}
43 51
44int 52int
45rand() 53rand()
46{ 54{
47 return ((next = next * 1103515245 + 12345) % ((u_int)RAND_MAX + 1)); 55
56 return (rand_r(&next));
48} 57}
49 58
50void 59void
51srand(seed) 60srand(seed)
52u_int seed; 61u_int seed;
53{ 62{
63
54 next = seed; 64 next = seed;
55} 65}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
index 5a772c9a8c..6b0831ead7 100644
--- a/src/lib/libc/stdlib/rand48.3
+++ b/src/lib/libc/stdlib/rand48.3
@@ -1,4 +1,4 @@
1\" Copyright (c) 1993 Martin Birgmeier 1.\" Copyright (c) 1993 Martin Birgmeier
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" You may redistribute unmodified or modified versions of this source 4.\" You may redistribute unmodified or modified versions of this source
@@ -9,7 +9,7 @@
9.\" of any kind. I shall in no event be liable for anything that happens 9.\" of any kind. I shall in no event be liable for anything that happens
10.\" to anyone/anything when using this software. 10.\" to anyone/anything when using this software.
11.\" 11.\"
12.\" $Id: rand48.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $ 12.\" $OpenBSD: rand48.3,v 1.9 2003/05/10 06:48:30 jmc Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd October 8, 1993
15.Dt RAND48 3 15.Dt RAND48 3
@@ -24,10 +24,10 @@
24.Nm srand48 , 24.Nm srand48 ,
25.Nm seed48 , 25.Nm seed48 ,
26.Nm lcong48 26.Nm lcong48
27.Nd pseudo random number generators and initialization routines 27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS 28.Sh SYNOPSIS
29.Fd #include <stdlib.h> 29.Fd #include <stdlib.h>
30.Ft double 30.Ft double
31.Fn drand48 void 31.Fn drand48 void
32.Ft double 32.Ft double
33.Fn erand48 "unsigned short xseed[3]" 33.Fn erand48 "unsigned short xseed[3]"
@@ -49,12 +49,13 @@
49The 49The
50.Fn rand48 50.Fn rand48
51family of functions generates pseudo-random numbers using a linear 51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size. The 52congruential algorithm working on integers 48 bits in size.
53particular formula employed is 53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m 54r(n+1) = (a * r(n) + c) mod m
55where the default values are 55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and 56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11. The modulus is always fixed at m = 2 ** 48. 57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
58r(n) is called the seed of the random number generator. 59r(n) is called the seed of the random number generator.
59.Pp 60.Pp
60For all the six generator routines described next, the first 61For all the six generator routines described next, the first
@@ -63,15 +64,17 @@ computational step is to perform a single iteration of the algorithm.
63.Fn drand48 64.Fn drand48
64and 65and
65.Fn erand48 66.Fn erand48
66return values of type double. The full 48 bits of r(n+1) are 67return values of type double.
68The full 48 bits of r(n+1) are
67loaded into the mantissa of the returned value, with the exponent set 69loaded into the mantissa of the returned value, with the exponent set
68such that the values produced lie in the interval [0.0, 1.0). 70such that the values produced lie in the interval [0.0, 1.0].
69.Pp 71.Pp
70.Fn lrand48 72.Fn lrand48
71and 73and
72.Fn nrand48 74.Fn nrand48
73return values of type long in the range 75return values of type long in the range
74[0, 2**31-1]. The high-order (31) bits of 76[0, 2**31-1].
77The high-order (31) bits of
75r(n+1) are loaded into the lower bits of the returned value, with 78r(n+1) are loaded into the lower bits of the returned value, with
76the topmost (sign) bit set to zero. 79the topmost (sign) bit set to zero.
77.Pp 80.Pp
@@ -79,14 +82,15 @@ the topmost (sign) bit set to zero.
79and 82and
80.Fn jrand48 83.Fn jrand48
81return values of type long in the range 84return values of type long in the range
82[-2**31, 2**31-1]. The high-order (32) bits of 85[-2**31, 2**31-1].
83r(n+1) are loaded into the returned value. 86The high-order (32) bits of r(n+1) are loaded into the returned value.
84.Pp 87.Pp
85.Fn drand48 , 88.Fn drand48 ,
86.Fn lrand48 , 89.Fn lrand48 ,
87and 90and
88.Fn mrand48 91.Fn mrand48
89use an internal buffer to store r(n). For these functions 92use an internal buffer to store r(n).
93For these functions
90the initial value of r(0) = 0x1234abcd330e = 20017429951246. 94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
91.Pp 95.Pp
92On the other hand, 96On the other hand,
@@ -118,12 +122,12 @@ also initializes the internal buffer r(n) of
118and 122and
119.Fn mrand48 , 123.Fn mrand48 ,
120but here all 48 bits of the seed can be specified in an array of 3 shorts, 124but here all 48 bits of the seed can be specified in an array of 3 shorts,
121where the zeroth member specifies the lowest bits. Again, 125where the zeroth member specifies the lowest bits.
122the constant multiplicand and addend of the algorithm are 126Again, the constant multiplicand and addend of the algorithm are
123reset to the default values given above. 127reset to the default values given above.
124.Fn seed48 128.Fn seed48
125returns a pointer to an array of 3 shorts which contains the old seed. 129returns a pointer to an array of 3 shorts which contains the old seed.
126This array is statically allocated, thus its contents are lost after 130This array is statically allocated, so its contents are lost after
127each new call to 131each new call to
128.Fn seed48 . 132.Fn seed48 .
129.Pp 133.Pp
@@ -152,9 +156,10 @@ always also set the multiplicand and addend for any of the six
152generator calls. 156generator calls.
153.Pp 157.Pp
154For a more powerful random number generator, see 158For a more powerful random number generator, see
155.Xr random 3 159.Xr random 3 .
156.Sh AUTHOR 160.Sh AUTHORS
157Martin Birgmeier 161Martin Birgmeier
158.Sh SEE ALSO 162.Sh SEE ALSO
163.Xr arc4random 3 ,
159.Xr rand 3 , 164.Xr rand 3 ,
160.Xr random 3 . 165.Xr random 3
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
index 12496d1c8c..afa49f65f3 100644
--- a/src/lib/libc/stdlib/rand48.h
+++ b/src/lib/libc/stdlib/rand48.h
@@ -9,6 +9,8 @@
9 * This software is provided ``as is'', and comes with no warranties 9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens 10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
12 */ 14 */
13 15
14#ifndef _RAND48_H_ 16#ifndef _RAND48_H_
@@ -17,7 +19,7 @@
17#include <math.h> 19#include <math.h>
18#include <stdlib.h> 20#include <stdlib.h>
19 21
20void __dorand48 __P((unsigned short[3])); 22void __dorand48(unsigned short[3]);
21 23
22#define RAND48_SEED_0 (0x330e) 24#define RAND48_SEED_0 (0x330e)
23#define RAND48_SEED_1 (0xabcd) 25#define RAND48_SEED_1 (0xabcd)
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
index 38c15a9803..b98917a442 100644
--- a/src/lib/libc/stdlib/random.3
+++ b/src/lib/libc/stdlib/random.3
@@ -29,97 +29,106 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)random.3 6.5 (Berkeley) 4/19/91 32.\" $OpenBSD: random.3,v 1.15 2003/05/10 06:48:30 jmc Exp $
33.\" $Id: random.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\" 33.\"
35.Dd April 19, 1991 34.Dd April 19, 1991
36.Dt RANDOM 3 35.Dt RANDOM 3
37.Os BSD 4.2 36.Os
38.Sh NAME 37.Sh NAME
39.Nm random , 38.Nm random ,
40.Nm srandom , 39.Nm srandom ,
40.Nm srandomdev ,
41.Nm initstate , 41.Nm initstate ,
42.Nm setstate 42.Nm setstate
43.Nd better random number generator; routines for changing generators 43.Nd better random number generator; routines for changing generators
44.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Fd #include <stdlib.h> 45.Fd #include <stdlib.h>
46.Ft long 46.Ft long
47.Fn random void 47.Fn random void
48.Ft void 48.Ft void
49.Fn srandom "unsigned seed" 49.Fn srandom "unsigned int seed"
50.Ft void
51.Fn srandomdev void
50.Ft char * 52.Ft char *
51.Fn initstate "unsigned seed" "char *state" "int n" 53.Fn initstate "unsigned int seed" "char *state" "size_t n"
52.Ft char * 54.Ft char *
53.Fn setstate "char *state" 55.Fn setstate "const char *state"
54.Sh DESCRIPTION 56.Sh DESCRIPTION
55The 57The
56.Fn random 58.Fn random
57function 59function uses a non-linear additive feedback random number generator employing
58uses a non-linear additive feedback random number generator employing a 60a default table of size 31 long integers to return successive pseudo-random
59default table of size 31 long integers to return successive pseudo-random 61numbers in the range from 0 to (2**31)\-1.
60numbers in the range from 0 to
61.if t 2\u\s731\s10\d\(mi1.
62.if n (2**31)\(mi1.
63The period of this random number generator is very large, approximately 62The period of this random number generator is very large, approximately
64.if t 16\(mu(2\u\s731\s10\d\(mi1). 6316*((2**31)\-1).
65.if n 16*((2**31)\(mi1).
66.Pp 64.Pp
67The 65The
68.Fn random Ns / Fn srandom 66.Fn random
69have (almost) the same calling sequence and initialization properties as 67and
70.Xr rand 3 Ns / Xr srand 3 . 68.Fn srandom
69functions have (almost) the same calling sequence and initialization
70properties as
71.Xr rand 3 Ns / Ns Xr srand 3 .
71The difference is that 72The difference is that
72.Xr rand 73.Xr rand
73produces a much less random sequence \(em in fact, the low dozen bits 74produces a much less random sequence \(em in fact, the low dozen bits
74generated by rand go through a cyclic pattern. All the bits generated by 75generated by rand go through a cyclic pattern.
76All the bits generated by
75.Fn random 77.Fn random
76are usable. For example, 78are usable.
79For example,
77.Sq Li random()&01 80.Sq Li random()&01
78will produce a random binary 81will produce a random binary
79value. 82value.
80.Pp 83.Pp
81Unlike 84Like
82.Xr srand ,
83.Fn srandom
84does not return the old seed; the reason for this is that the amount of
85state information used is much more than a single word. (Two other
86routines are provided to deal with restarting/changing random
87number generators). Like
88.Xr rand 3 , 85.Xr rand 3 ,
89however,
90.Fn random 86.Fn random
91will by default produce a sequence of numbers that can be duplicated 87will by default produce a sequence of numbers that can be duplicated
92by calling 88by calling
93.Fn srandom 89.Fn srandom
94with 90with
95.Ql 1 91.Ql 1
96as the seed. 92as the seed.
97.Pp 93.Pp
98The 94The
95.Fn srandomdev
96routine initializes a state array using the
97.Xr arandom 4
98random number device which returns good random numbers,
99suitable for cryptographic use.
100Note that this particular seeding procedure can generate
101states which are impossible to reproduce by calling
102.Fn srandom
103with any value, since the succeeding terms in the
104state buffer are no longer derived from the LC algorithm applied to
105a fixed seed.
106.Pp
107The
99.Fn initstate 108.Fn initstate
100routine allows a state array, passed in as an argument, to be initialized 109routine allows a state array, passed in as an argument, to be initialized
101for future use. The size of the state array (in bytes) is used by 110for future use.
111The size of the state array (in bytes) is used by
102.Fn initstate 112.Fn initstate
103to decide how sophisticated a random number generator it should use \(em the 113to decide how sophisticated a random number generator it should use \(em the
104more state, the better the random numbers will be. 114more state, the better the random numbers will be.
105(Current "optimal" values for the amount of state information are 115(Current "optimal" values for the amount of state information are
1068, 32, 64, 128, and 256 bytes; other amounts will be rounded down to 1168, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
107the nearest known amount. Using less than 8 bytes will cause an error.) 117the nearest known amount.
118Using less than 8 bytes will cause an error.)
108The seed for the initialization (which specifies a starting point for 119The seed for the initialization (which specifies a starting point for
109the random number sequence, and provides for restarting at the same 120the random number sequence, and provides for restarting at the same
110point) is also an argument. 121point) is also an argument.
111The 122The
112.Fn initstate 123.Fn initstate
113function 124function returns a pointer to the previous state information array.
114returns a pointer to the previous state information array.
115.Pp 125.Pp
116Once a state has been initialized, the 126Once a state has been initialized, the
117.Fn setstate 127.Fn setstate
118routine provides for rapid switching between states. 128routine provides for rapid switching between states.
119The 129The
120.Fn setstate 130.Fn setstate
121function 131function returns a pointer to the previous state array; its
122returns a pointer to the previous state array; its
123argument state array is used for further random number generation 132argument state array is used for further random number generation
124until the next call to 133until the next call to
125.Fn initstate 134.Fn initstate
@@ -143,12 +152,10 @@ is that the size of the state array does not have to be remembered after
143it is initialized. 152it is initialized.
144.Pp 153.Pp
145With 256 bytes of state information, the period of the random number 154With 256 bytes of state information, the period of the random number
146generator is greater than 155generator is greater than 2**69
147.if t 2\u\s769\s10\d,
148.if n 2**69
149which should be sufficient for most purposes. 156which should be sufficient for most purposes.
150.Sh AUTHOR 157.Sh AUTHORS
151Earl T. Cohen 158.An Earl T. Cohen
152.Sh DIAGNOSTICS 159.Sh DIAGNOSTICS
153If 160If
154.Fn initstate 161.Fn initstate
@@ -157,10 +164,26 @@ is called with less than 8 bytes of state information, or if
157detects that the state information has been garbled, error 164detects that the state information has been garbled, error
158messages are printed on the standard error output. 165messages are printed on the standard error output.
159.Sh SEE ALSO 166.Sh SEE ALSO
160.Xr rand 3 167.Xr arc4random 3 ,
168.Xr drand48 3 ,
169.Xr rand 3 ,
170.Xr random 4
171.Sh STANDARDS
172The
173.Fn random ,
174.Fn srandom ,
175.Fn initstate ,
176and
177.Fn setstate
178functions conform to
179.St -xpg4.2 .
180.Pp
181The
182.Fn srandomdev
183function is an extension.
161.Sh HISTORY 184.Sh HISTORY
162These 185These
163functions appeared in 186functions appeared in
164.Bx 4.2 . 187.Bx 4.2 .
165.Sh BUGS 188.Sh BUGS
166About 2/3 the speed of 189About 2/3 the speed of
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..49a5ed1c3e 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,16 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: random.c,v 1.11 2003/02/28 21:27:44 millert Exp $";
36static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#include <sys/param.h>
39#include <sys/sysctl.h>
40#include <sys/time.h>
41#include <fcntl.h>
39#include <stdio.h> 42#include <stdio.h>
40#include <stdlib.h> 43#include <stdlib.h>
44#include <unistd.h>
41 45
42/* 46/*
43 * random.c: 47 * random.c:
@@ -55,10 +59,10 @@ static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
55 * congruential generator. If the amount of state information is less than 59 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used. 60 * 32 bytes, a simple linear congruential R.N.G. is used.
57 * 61 *
58 * Internally, the state information is treated as an array of longs; the 62 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small 63 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the 64 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of 65 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note: 66 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information 67 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details). 68 * stored in it -- see setstate() for details).
@@ -134,14 +138,14 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. 138 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */ 139 */
136 140
137static long randtbl[DEG_3 + 1] = { 141static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3, 142 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 143 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 144 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 145 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 146 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 147 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 148 0xf3bec5da,
145}; 149};
146 150
147/* 151/*
@@ -158,8 +162,8 @@ static long randtbl[DEG_3 + 1] = {
158 * in the initialization of randtbl) because the state table pointer is set 162 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below). 163 * to point to randtbl[1] (as explained below).
160 */ 164 */
161static long *fptr = &randtbl[SEP_3 + 1]; 165static int32_t *fptr = &randtbl[SEP_3 + 1];
162static long *rptr = &randtbl[1]; 166static int32_t *rptr = &randtbl[1];
163 167
164/* 168/*
165 * The following things are the pointer to the state information table, the 169 * The following things are the pointer to the state information table, the
@@ -171,11 +175,11 @@ static long *rptr = &randtbl[1];
171 * this is more efficient than indexing every time to find the address of 175 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped. 176 * the last element to see if the front and rear pointers have wrapped.
173 */ 177 */
174static long *state = &randtbl[1]; 178static int32_t *state = &randtbl[1];
179static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3; 180static int rand_type = TYPE_3;
176static int rand_deg = DEG_3; 181static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 182static int rand_sep = SEP_3;
178static long *end_ptr = &randtbl[DEG_3 + 1];
179 183
180/* 184/*
181 * srandom: 185 * srandom:
@@ -191,17 +195,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
191 */ 195 */
192void 196void
193srandom(x) 197srandom(x)
194 u_int x; 198 unsigned int x;
195{ 199{
196 register int i, j; 200 int i;
201 int32_t test;
202 div_t val;
197 203
198 if (rand_type == TYPE_0) 204 if (rand_type == TYPE_0)
199 state[0] = x; 205 state[0] = x;
200 else { 206 else {
201 j = 1;
202 state[0] = x; 207 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 208 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 209 /*
210 * Implement the following, without overflowing 31 bits:
211 *
212 * state[i] = (16807 * state[i - 1]) % 2147483647;
213 *
214 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
215 */
216 val = div(state[i-1], 127773);
217 test = 16807 * val.rem - 2836 * val.quot;
218 state[i] = test + (test < 0 ? 2147483647 : 0);
219 }
205 fptr = &state[rand_sep]; 220 fptr = &state[rand_sep];
206 rptr = &state[0]; 221 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 222 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +225,65 @@ srandom(x)
210} 225}
211 226
212/* 227/*
228 * srandomdev:
229 *
230 * Many programs choose the seed value in a totally predictable manner.
231 * This often causes problems. We seed the generator using the much more
232 * secure arandom(4) interface. Note that this particular seeding
233 * procedure can generate states which are impossible to reproduce by
234 * calling srandom() with any value, since the succeeding terms in the
235 * state buffer are no longer derived from the LC algorithm applied to
236 * a fixed seed.
237 */
238void
239srandomdev()
240{
241 int fd, i, mib[2], n;
242 size_t len;
243
244 if (rand_type == TYPE_0)
245 len = sizeof(state[0]);
246 else
247 len = rand_deg * sizeof(state[0]);
248
249 /*
250 * To get seed data, first try reading from /dev/arandom.
251 * If that fails, try the KERN_ARND sysctl() (one int at a time).
252 * As a last resort, call srandom().
253 */
254 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
255 read(fd, (void *) state, len) == (ssize_t) len) {
256 close(fd);
257 } else {
258 if (fd != -1)
259 close(fd);
260 mib[0] = CTL_KERN;
261 mib[1] = KERN_ARND;
262 n = len / sizeof(int);
263 len = sizeof(int);
264 for (i = 0; i < n; i++) {
265 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
266 NULL, 0) == -1)
267 break;
268 }
269 if (i != n) {
270 struct timeval tv;
271 u_int junk;
272
273 /* XXX - this could be better */
274 gettimeofday(&tv, NULL);
275 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
276 return;
277 }
278 }
279
280 if (rand_type != TYPE_0) {
281 fptr = &state[rand_sep];
282 rptr = &state[0];
283 }
284}
285
286/*
213 * initstate: 287 * initstate:
214 * 288 *
215 * Initialize the state information in the given array of n bytes for future 289 * Initialize the state information in the given array of n bytes for future
@@ -232,19 +306,16 @@ char *
232initstate(seed, arg_state, n) 306initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 307 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 308 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 309 size_t n; /* # bytes of state info */
236{ 310{
237 register char *ostate = (char *)(&state[-1]); 311 char *ostate = (char *)(&state[-1]);
238 312
239 if (rand_type == TYPE_0) 313 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 314 state[-1] = rand_type;
241 else 315 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 316 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 317 if (n < BREAK_0)
244 (void)fprintf(stderr, 318 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 319 if (n < BREAK_1) {
249 rand_type = TYPE_0; 320 rand_type = TYPE_0;
250 rand_deg = DEG_0; 321 rand_deg = DEG_0;
@@ -266,7 +337,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 337 rand_deg = DEG_4;
267 rand_sep = SEP_4; 338 rand_sep = SEP_4;
268 } 339 }
269 state = &(((long *)arg_state)[1]); /* first location */ 340 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 341 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 342 srandom(seed);
272 if (rand_type == TYPE_0) 343 if (rand_type == TYPE_0)
@@ -293,11 +364,11 @@ initstate(seed, arg_state, n)
293 */ 364 */
294char * 365char *
295setstate(arg_state) 366setstate(arg_state)
296 char *arg_state; 367 const char *arg_state;
297{ 368{
298 register long *new_state = (long *)arg_state; 369 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 370 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 371 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 372 char *ostate = (char *)(&state[-1]);
302 373
303 if (rand_type == TYPE_0) 374 if (rand_type == TYPE_0)
@@ -315,8 +386,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 386 rand_sep = seps[type];
316 break; 387 break;
317 default: 388 default:
318 (void)fprintf(stderr, 389 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 390 }
321 state = &new_state[1]; 391 state = &new_state[1];
322 if (rand_type != TYPE_0) { 392 if (rand_type != TYPE_0) {
@@ -347,7 +417,7 @@ setstate(arg_state)
347long 417long
348random() 418random()
349{ 419{
350 long i; 420 int32_t i;
351 421
352 if (rand_type == TYPE_0) 422 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 423 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +430,5 @@ random()
360 } else if (++rptr >= end_ptr) 430 } else if (++rptr >= end_ptr)
361 rptr = state; 431 rptr = state;
362 } 432 }
363 return(i); 433 return((long)i);
364} 434}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
index 9d8b1ff2ce..56fbea9ede 100644
--- a/src/lib/libc/stdlib/realpath.3
+++ b/src/lib/libc/stdlib/realpath.3
@@ -32,10 +32,9 @@
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE. 33.\" SUCH DAMAGE.
34.\" 34.\"
35.\" from: @(#)realpath.3 8.2 (Berkeley) 2/16/94 35.\" $OpenBSD: realpath.3,v 1.8 2001/04/23 15:30:25 aaron Exp $
36.\" $Id: realpath.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
37.\" 36.\"
38.Dd "February 16, 1994" 37.Dd February 16, 1994
39.Dt REALPATH 3 38.Dt REALPATH 3
40.Os 39.Os
41.Sh NAME 40.Sh NAME
@@ -57,8 +56,7 @@ and
57.Pa /../ 56.Pa /../
58in 57in
59.Fa pathname , 58.Fa pathname ,
60and copies the resulting absolute pathname into 59and copies the resulting absolute pathname into the memory referenced by
61the memory referenced by
62.Fa resolvedname . 60.Fa resolvedname .
63The 61The
64.Fa resolvedname 62.Fa resolvedname
@@ -68,7 +66,7 @@ refer to a buffer capable of storing at least
68.Dv MAXPATHLEN 66.Dv MAXPATHLEN
69characters. 67characters.
70.Pp 68.Pp
71The 69The
72.Fn realpath 70.Fn realpath
73function will resolve both absolute and relative paths 71function will resolve both absolute and relative paths
74and return the absolute pathname corresponding to 72and return the absolute pathname corresponding to
@@ -82,14 +80,14 @@ is called.
82The 80The
83.Fn realpath 81.Fn realpath
84function returns 82function returns
85.Fa resolved_name 83.Fa resolvedname
86on success. 84on success.
87If an error occurs, 85If an error occurs,
88.Fn realpath 86.Fn realpath
89returns 87returns
90.Dv NULL , 88.Dv NULL ,
91and 89and
92.Fa resolved_name 90.Fa resolvedname
93contains the pathname which caused the problem. 91contains the pathname which caused the problem.
94.Sh ERRORS 92.Sh ERRORS
95The function 93The function
@@ -102,7 +100,7 @@ for any of the errors specified for the library functions
102.Xr fchdir 2 , 100.Xr fchdir 2 ,
103.Xr lstat 2 , 101.Xr lstat 2 ,
104.Xr open 2 , 102.Xr open 2 ,
105.Xr readlink 2 103.Xr readlink 2 ,
106and 104and
107.Xr getcwd 3 . 105.Xr getcwd 3 .
108.Sh CAVEATS 106.Sh CAVEATS
@@ -114,10 +112,10 @@ The
114version always returns absolute pathnames, 112version always returns absolute pathnames,
115whereas the Solaris implementation will, 113whereas the Solaris implementation will,
116under certain circumstances, return a relative 114under certain circumstances, return a relative
117.Fa resolved_path 115.Fa resolvedname
118when given a relative 116when given a relative
119.Fa pathname . 117.Fa pathname .
120.Sh "SEE ALSO" 118.Sh SEE ALSO
121.Xr getcwd 3 119.Xr getcwd 3
122.Sh HISTORY 120.Sh HISTORY
123The 121The
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index e349b7e068..71063394d1 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)realpath.c 8.1 (Berkeley) 2/16/94";*/ 38static char *rcsid = "$OpenBSD: realpath.c,v 1.8 2003/04/04 22:47:43 hin Exp $";
39static char *rcsid = "$Id: realpath.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <sys/param.h> 41#include <sys/param.h>
@@ -63,13 +62,18 @@ realpath(path, resolved)
63 struct stat sb; 62 struct stat sb;
64 int fd, n, rootd, serrno; 63 int fd, n, rootd, serrno;
65 char *p, *q, wbuf[MAXPATHLEN]; 64 char *p, *q, wbuf[MAXPATHLEN];
65 int symlinks = 0;
66 66
67 /* Save the starting point. */ 67 /* Save the starting point. */
68 if ((fd = open(".", O_RDONLY)) < 0) { 68 if ((fd = open(".", O_RDONLY)) < 0) {
69 (void)strcpy(resolved, "."); 69 (void)strlcpy(resolved, ".", MAXPATHLEN);
70 return (NULL); 70 return (NULL);
71 } 71 }
72 72
73 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
74 if (path[0] == '.' && path[1] == '\0')
75 path = "";
76
73 /* 77 /*
74 * Find the dirname and basename from the path to be resolved. 78 * Find the dirname and basename from the path to be resolved.
75 * Change directory to the dirname component. 79 * Change directory to the dirname component.
@@ -78,8 +82,7 @@ realpath(path, resolved)
78 * if it is a directory, then change to that directory. 82 * if it is a directory, then change to that directory.
79 * get the current directory name and append the basename. 83 * get the current directory name and append the basename.
80 */ 84 */
81 (void)strncpy(resolved, path, MAXPATHLEN - 1); 85 strlcpy(resolved, path, MAXPATHLEN);
82 resolved[MAXPATHLEN - 1] = '\0';
83loop: 86loop:
84 q = strrchr(resolved, '/'); 87 q = strrchr(resolved, '/');
85 if (q != NULL) { 88 if (q != NULL) {
@@ -99,9 +102,13 @@ loop:
99 p = resolved; 102 p = resolved;
100 103
101 /* Deal with the last component. */ 104 /* Deal with the last component. */
102 if (lstat(p, &sb) == 0) { 105 if (*p != '\0' && lstat(p, &sb) == 0) {
103 if (S_ISLNK(sb.st_mode)) { 106 if (S_ISLNK(sb.st_mode)) {
104 n = readlink(p, resolved, MAXPATHLEN); 107 if (++symlinks > MAXSYMLINKS) {
108 errno = ELOOP;
109 goto err1;
110 }
111 n = readlink(p, resolved, MAXPATHLEN-1);
105 if (n < 0) 112 if (n < 0)
106 goto err1; 113 goto err1;
107 resolved[n] = '\0'; 114 resolved[n] = '\0';
@@ -118,7 +125,7 @@ loop:
118 * Save the last component name and get the full pathname of 125 * Save the last component name and get the full pathname of
119 * the current directory. 126 * the current directory.
120 */ 127 */
121 (void)strcpy(wbuf, p); 128 (void)strlcpy(wbuf, p, sizeof wbuf);
122 if (getcwd(resolved, MAXPATHLEN) == 0) 129 if (getcwd(resolved, MAXPATHLEN) == 0)
123 goto err1; 130 goto err1;
124 131
@@ -137,8 +144,8 @@ loop:
137 goto err1; 144 goto err1;
138 } 145 }
139 if (rootd == 0) 146 if (rootd == 0)
140 (void)strcat(resolved, "/"); 147 strlcat(resolved, "/", MAXPATHLEN);
141 (void)strcat(resolved, wbuf); 148 strlcat(resolved, wbuf, MAXPATHLEN);
142 } 149 }
143 150
144 /* Go back to where we came from. */ 151 /* Go back to where we came from. */
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..f4c5769a8c
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43remque(void *element)
44{
45 struct qelem *e = (struct qelem *) element;
46 e->q_forw->q_back = e->q_back;
47 e->q_back->q_forw = e->q_forw;
48}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
index e3d31901dd..c4dcd0ead8 100644
--- a/src/lib/libc/stdlib/seed48.c
+++ b/src/lib/libc/stdlib/seed48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: seed48.c,v 1.2 1996/08/19 08:33:48 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
index a36669888d..044f01b1c9 100644
--- a/src/lib/libc/stdlib/setenv.c
+++ b/src/lib/libc/stdlib/setenv.c
@@ -32,13 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/ 35static char *rcsid = "$OpenBSD: setenv.c,v 1.5 2002/12/10 22:44:13 mickey Exp $";
36static char *rcsid = "$Id: setenv.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
41 40
41char *__findenv(const char *name, int *offset);
42
42/* 43/*
43 * setenv -- 44 * setenv --
44 * Set the value of the environmental variable "name" to be 45 * Set the value of the environmental variable "name" to be
@@ -54,7 +55,6 @@ setenv(name, value, rewrite)
54 static int alloced; /* if allocated space before */ 55 static int alloced; /* if allocated space before */
55 register char *C; 56 register char *C;
56 int l_value, offset; 57 int l_value, offset;
57 char *__findenv();
58 58
59 if (*value == '=') /* no `=' in value */ 59 if (*value == '=') /* no `=' in value */
60 ++value; 60 ++value;
@@ -63,7 +63,8 @@ setenv(name, value, rewrite)
63 if (!rewrite) 63 if (!rewrite)
64 return (0); 64 return (0);
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 65 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 66 while ((*C++ = *value++))
67 ;
67 return (0); 68 return (0);
68 } 69 }
69 } else { /* create new slot */ 70 } else { /* create new slot */
@@ -72,10 +73,11 @@ setenv(name, value, rewrite)
72 73
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 74 for (P = environ, cnt = 0; *P; ++P, ++cnt);
74 if (alloced) { /* just increase size */ 75 if (alloced) { /* just increase size */
75 environ = (char **)realloc((char *)environ, 76 P = (char **)realloc((void *)environ,
76 (size_t)(sizeof(char *) * (cnt + 2))); 77 (size_t)(sizeof(char *) * (cnt + 2)));
77 if (!environ) 78 if (!P)
78 return (-1); 79 return (-1);
80 environ = P;
79 } 81 }
80 else { /* get new space */ 82 else { /* get new space */
81 alloced = 1; /* copy old entries into it */ 83 alloced = 1; /* copy old entries into it */
@@ -95,7 +97,7 @@ setenv(name, value, rewrite)
95 return (-1); 97 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 98 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 99 ;
98 for (*C++ = '='; *C++ = *value++; ) 100 for (*C++ = '='; (*C++ = *value++); )
99 ; 101 ;
100 return (0); 102 return (0);
101} 103}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
index daf733f93e..fcff8a172e 100644
--- a/src/lib/libc/stdlib/srand48.c
+++ b/src/lib/libc/stdlib/srand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: srand48.c,v 1.2 1996/08/19 08:33:49 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
index 0b7f973857..4e04f6738e 100644
--- a/src/lib/libc/stdlib/strtod.3
+++ b/src/lib/libc/stdlib/strtod.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtod.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strtod.3,v 1.7 2000/04/20 13:50:03 aaron Exp $
37.\" $Id: strtod.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRTOD 3 39.Dt STRTOD 3
@@ -51,20 +50,25 @@ string to double
51.Sh DESCRIPTION 50.Sh DESCRIPTION
52The 51The
53.Fn strtod 52.Fn strtod
54function converts the initial portion of the string 53function converts the initial portion of the string pointed to by
55pointed to by
56.Fa nptr 54.Fa nptr
57to 55to
58.Em double 56.Li double
59representation. 57representation.
60.Pp 58.Pp
61The expected form of the string is an optional plus (``+'') or minus 59The expected form of the string is an optional plus
62sign (``-'') followed by a sequence of digits optionally containing 60.Pq Ql +
61or minus sign
62.Pq Ql -
63followed by a sequence of digits optionally containing
63a decimal-point character, optionally followed by an exponent. 64a decimal-point character, optionally followed by an exponent.
64An exponent consists of an ``E'' or ``e'', followed by an optional plus 65An exponent consists of an
65or minus sign, followed by a sequence of digits. 66.Sq E
67or
68.Sq e ,
69followed by an optional plus or minus sign, followed by a sequence of digits.
66.Pp 70.Pp
67Leading white-space characters in the string (as defined by the 71Leading whitespace characters in the string (as defined by the
68.Xr isspace 3 72.Xr isspace 3
69function) are skipped. 73function) are skipped.
70.Sh RETURN VALUES 74.Sh RETURN VALUES
@@ -88,18 +92,18 @@ is stored in the location referenced by
88If the correct value would cause overflow, plus or minus 92If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL 93.Dv HUGE_VAL
90is returned (according to the sign of the value), and 94is returned (according to the sign of the value), and
91.Dv ERANGE 95.Er ERANGE
92is stored in 96is stored in
93.Va errno . 97.Va errno .
94If the correct value would cause underflow, zero is 98If the correct value would cause underflow, zero is returned and
95returned and 99.Er ERANGE
96.Dv ERANGE 100is stored in
97is stored in
98.Va errno . 101.Va errno .
99.Sh ERRORS 102.Sh ERRORS
100.Bl -tag -width Er 103.Bl -tag -width Er
101.It Bq Er ERANGE 104.It Bq Er ERANGE
102Overflow or underflow occurred. 105Overflow or underflow occurred.
106.El
103.Sh SEE ALSO 107.Sh SEE ALSO
104.Xr atof 3 , 108.Xr atof 3 ,
105.Xr atoi 3 , 109.Xr atoi 3 ,
@@ -109,6 +113,5 @@ Overflow or underflow occurred.
109.Sh STANDARDS 113.Sh STANDARDS
110The 114The
111.Fn strtod 115.Fn strtod
112function 116function conforms to
113conforms to
114.St -ansiC . 117.St -ansiC .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
index b13fa128f5..17d26a1dc3 100644
--- a/src/lib/libc/stdlib/strtod.c
+++ b/src/lib/libc/stdlib/strtod.c
@@ -90,12 +90,13 @@
90 */ 90 */
91 91
92#if defined(LIBC_SCCS) && !defined(lint) 92#if defined(LIBC_SCCS) && !defined(lint)
93static char *rcsid = "$Id: strtod.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"; 93static char *rcsid = "$OpenBSD: strtod.c,v 1.16 2002/12/02 15:38:54 millert Exp $";
94#endif /* LIBC_SCCS and not lint */ 94#endif /* LIBC_SCCS and not lint */
95 95
96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) 97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
98#include <machine/endian.h> 98 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__)
99#include <sys/types.h>
99#if BYTE_ORDER == BIG_ENDIAN 100#if BYTE_ORDER == BIG_ENDIAN
100#define IEEE_BIG_ENDIAN 101#define IEEE_BIG_ENDIAN
101#else 102#else
@@ -103,7 +104,16 @@ static char *rcsid = "$Id: strtod.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
103#endif 104#endif
104#endif 105#endif
105 106
106#ifdef vax 107#ifdef __arm32__
108/*
109 * Although the CPU is little endian the FP has different
110 * byte and word endianness. The byte order is still little endian
111 * but the word order is big endian.
112 */
113#define IEEE_BIG_ENDIAN
114#endif
115
116#ifdef __vax__
107#define VAX 117#define VAX
108#endif 118#endif
109 119
@@ -143,7 +153,6 @@ extern void *MALLOC(size_t);
143#include "errno.h" 153#include "errno.h"
144 154
145#ifdef Bad_float_h 155#ifdef Bad_float_h
146#undef __STDC__
147#ifdef IEEE_BIG_ENDIAN 156#ifdef IEEE_BIG_ENDIAN
148#define IEEE_ARITHMETIC 157#define IEEE_ARITHMETIC
149#endif 158#endif
@@ -212,19 +221,24 @@ Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
212IBM should be defined. 221IBM should be defined.
213#endif 222#endif
214 223
224typedef union {
225 double d;
226 ULong ul[2];
227} _double;
228#define value(x) ((x).d)
215#ifdef IEEE_LITTLE_ENDIAN 229#ifdef IEEE_LITTLE_ENDIAN
216#define word0(x) ((ULong *)&x)[1] 230#define word0(x) ((x).ul[1])
217#define word1(x) ((ULong *)&x)[0] 231#define word1(x) ((x).ul[0])
218#else 232#else
219#define word0(x) ((ULong *)&x)[0] 233#define word0(x) ((x).ul[0])
220#define word1(x) ((ULong *)&x)[1] 234#define word1(x) ((x).ul[1])
221#endif 235#endif
222 236
223/* The following definition of Storeinc is appropriate for MIPS processors. 237/* The following definition of Storeinc is appropriate for MIPS processors.
224 * An alternative that might be better on some machines is 238 * An alternative that might be better on some machines is
225 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) 239 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
226 */ 240 */
227#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) 241#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm32__)
228#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ 242#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
229((unsigned short *)a)[0] = (unsigned short)c, a++) 243((unsigned short *)a)[0] = (unsigned short)c, a++)
230#else 244#else
@@ -380,7 +394,7 @@ Balloc
380 int x; 394 int x;
381 Bigint *rv; 395 Bigint *rv;
382 396
383 if (rv = freelist[k]) { 397 if ((rv = freelist[k])) {
384 freelist[k] = rv->next; 398 freelist[k] = rv->next;
385 } 399 }
386 else { 400 else {
@@ -628,7 +642,7 @@ mult
628 xc0 = c->x; 642 xc0 = c->x;
629#ifdef Pack_32 643#ifdef Pack_32
630 for(; xb < xbe; xb++, xc0++) { 644 for(; xb < xbe; xb++, xc0++) {
631 if (y = *xb & 0xffff) { 645 if ((y = *xb & 0xffff)) {
632 x = xa; 646 x = xa;
633 xc = xc0; 647 xc = xc0;
634 carry = 0; 648 carry = 0;
@@ -642,7 +656,7 @@ mult
642 while(x < xae); 656 while(x < xae);
643 *xc = carry; 657 *xc = carry;
644 } 658 }
645 if (y = *xb >> 16) { 659 if ((y = *xb >> 16)) {
646 x = xa; 660 x = xa;
647 xc = xc0; 661 xc = xc0;
648 carry = 0; 662 carry = 0;
@@ -693,7 +707,7 @@ pow5mult
693 int i; 707 int i;
694 static int p05[3] = { 5, 25, 125 }; 708 static int p05[3] = { 5, 25, 125 };
695 709
696 if (i = k & 3) 710 if ((i = k & 3))
697 b = multadd(b, p05[i-1], 0); 711 b = multadd(b, p05[i-1], 0);
698 712
699 if (!(k >>= 2)) 713 if (!(k >>= 2))
@@ -756,7 +770,7 @@ lshift
756 z = *x++ >> k1; 770 z = *x++ >> k1;
757 } 771 }
758 while(x < xe); 772 while(x < xe);
759 if (*x1 = z) 773 if ((*x1 = z))
760 ++n1; 774 ++n1;
761 } 775 }
762#else 776#else
@@ -899,14 +913,16 @@ diff
899 static double 913 static double
900ulp 914ulp
901#ifdef KR_headers 915#ifdef KR_headers
902 (x) double x; 916 (_x) double _x;
903#else 917#else
904 (double x) 918 (double _x)
905#endif 919#endif
906{ 920{
921 _double x;
907 register Long L; 922 register Long L;
908 double a; 923 _double a;
909 924
925 value(x) = _x;
910 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; 926 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
911#ifndef Sudden_Underflow 927#ifndef Sudden_Underflow
912 if (L > 0) { 928 if (L > 0) {
@@ -931,7 +947,7 @@ ulp
931 } 947 }
932 } 948 }
933#endif 949#endif
934 return a; 950 return value(a);
935 } 951 }
936 952
937 static double 953 static double
@@ -944,7 +960,7 @@ b2d
944{ 960{
945 ULong *xa, *xa0, w, y, z; 961 ULong *xa, *xa0, w, y, z;
946 int k; 962 int k;
947 double d; 963 _double d;
948#ifdef VAX 964#ifdef VAX
949 ULong d0, d1; 965 ULong d0, d1;
950#else 966#else
@@ -1001,22 +1017,27 @@ b2d
1001#undef d0 1017#undef d0
1002#undef d1 1018#undef d1
1003#endif 1019#endif
1004 return d; 1020 return value(d);
1005 } 1021 }
1006 1022
1007 static Bigint * 1023 static Bigint *
1008d2b 1024d2b
1009#ifdef KR_headers 1025#ifdef KR_headers
1010 (d, e, bits) double d; int *e, *bits; 1026 (_d, e, bits) double d; int *e, *bits;
1011#else 1027#else
1012 (double d, int *e, int *bits) 1028 (double _d, int *e, int *bits)
1013#endif 1029#endif
1014{ 1030{
1015 Bigint *b; 1031 Bigint *b;
1016 int de, i, k; 1032 int de, i, k;
1017 ULong *x, y, z; 1033 ULong *x, y, z;
1034 _double d;
1018#ifdef VAX 1035#ifdef VAX
1019 ULong d0, d1; 1036 ULong d0, d1;
1037#endif
1038
1039 value(d) = _d;
1040#ifdef VAX
1020 d0 = word0(d) >> 16 | word0(d) << 16; 1041 d0 = word0(d) >> 16 | word0(d) << 16;
1021 d1 = word1(d) >> 16 | word1(d) << 16; 1042 d1 = word1(d) >> 16 | word1(d) << 16;
1022#else 1043#else
@@ -1141,11 +1162,11 @@ ratio
1141 (Bigint *a, Bigint *b) 1162 (Bigint *a, Bigint *b)
1142#endif 1163#endif
1143{ 1164{
1144 double da, db; 1165 _double da, db;
1145 int k, ka, kb; 1166 int k, ka, kb;
1146 1167
1147 da = b2d(a, &ka); 1168 value(da) = b2d(a, &ka);
1148 db = b2d(b, &kb); 1169 value(db) = b2d(b, &kb);
1149#ifdef Pack_32 1170#ifdef Pack_32
1150 k = ka - kb + 32*(a->wds - b->wds); 1171 k = ka - kb + 32*(a->wds - b->wds);
1151#else 1172#else
@@ -1171,7 +1192,7 @@ ratio
1171 word0(db) += k*Exp_msk1; 1192 word0(db) += k*Exp_msk1;
1172 } 1193 }
1173#endif 1194#endif
1174 return da / db; 1195 return value(da) / value(db);
1175 } 1196 }
1176 1197
1177static CONST double 1198static CONST double
@@ -1211,7 +1232,8 @@ strtod
1211 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, 1232 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1212 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; 1233 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1213 CONST char *s, *s0, *s1; 1234 CONST char *s, *s0, *s1;
1214 double aadj, aadj1, adj, rv, rv0; 1235 double aadj, aadj1, adj;
1236 _double rv, rv0;
1215 Long L; 1237 Long L;
1216 ULong y, z; 1238 ULong y, z;
1217 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; 1239 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
@@ -1223,10 +1245,10 @@ strtod
1223#endif 1245#endif
1224 1246
1225 sign = nz0 = nz = 0; 1247 sign = nz0 = nz = 0;
1226 rv = 0.; 1248 value(rv) = 0.;
1227 1249
1228 1250
1229 for(s = s00; isspace(*s); s++) 1251 for(s = s00; isspace((unsigned char) *s); s++)
1230 ; 1252 ;
1231 1253
1232 if (*s == '-') { 1254 if (*s == '-') {
@@ -1340,9 +1362,9 @@ strtod
1340 if (!nd0) 1362 if (!nd0)
1341 nd0 = nd; 1363 nd0 = nd;
1342 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; 1364 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1343 rv = y; 1365 value(rv) = y;
1344 if (k > 9) 1366 if (k > 9)
1345 rv = tens[k - 9] * rv + z; 1367 value(rv) = tens[k - 9] * value(rv) + z;
1346 bd0 = 0; 1368 bd0 = 0;
1347 if (nd <= DBL_DIG 1369 if (nd <= DBL_DIG
1348#ifndef RND_PRODQUOT 1370#ifndef RND_PRODQUOT
@@ -1356,7 +1378,8 @@ strtod
1356#ifdef VAX 1378#ifdef VAX
1357 goto vax_ovfl_check; 1379 goto vax_ovfl_check;
1358#else 1380#else
1359 /* rv = */ rounded_product(rv, tens[e]); 1381 /* value(rv) = */ rounded_product(value(rv),
1382 tens[e]);
1360 goto ret; 1383 goto ret;
1361#endif 1384#endif
1362 } 1385 }
@@ -1366,27 +1389,30 @@ strtod
1366 * this for larger i values. 1389 * this for larger i values.
1367 */ 1390 */
1368 e -= i; 1391 e -= i;
1369 rv *= tens[i]; 1392 value(rv) *= tens[i];
1370#ifdef VAX 1393#ifdef VAX
1371 /* VAX exponent range is so narrow we must 1394 /* VAX exponent range is so narrow we must
1372 * worry about overflow here... 1395 * worry about overflow here...
1373 */ 1396 */
1374 vax_ovfl_check: 1397 vax_ovfl_check:
1375 word0(rv) -= P*Exp_msk1; 1398 word0(rv) -= P*Exp_msk1;
1376 /* rv = */ rounded_product(rv, tens[e]); 1399 /* value(rv) = */ rounded_product(value(rv),
1400 tens[e]);
1377 if ((word0(rv) & Exp_mask) 1401 if ((word0(rv) & Exp_mask)
1378 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) 1402 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1379 goto ovfl; 1403 goto ovfl;
1380 word0(rv) += P*Exp_msk1; 1404 word0(rv) += P*Exp_msk1;
1381#else 1405#else
1382 /* rv = */ rounded_product(rv, tens[e]); 1406 /* value(rv) = */ rounded_product(value(rv),
1407 tens[e]);
1383#endif 1408#endif
1384 goto ret; 1409 goto ret;
1385 } 1410 }
1386 } 1411 }
1387#ifndef Inaccurate_Divide 1412#ifndef Inaccurate_Divide
1388 else if (e >= -Ten_pmax) { 1413 else if (e >= -Ten_pmax) {
1389 /* rv = */ rounded_quotient(rv, tens[-e]); 1414 /* value(rv) = */ rounded_quotient(value(rv),
1415 tens[-e]);
1390 goto ret; 1416 goto ret;
1391 } 1417 }
1392#endif 1418#endif
@@ -1397,13 +1423,13 @@ strtod
1397 1423
1398 if (e1 > 0) { 1424 if (e1 > 0) {
1399 if (i = e1 & 15) 1425 if (i = e1 & 15)
1400 rv *= tens[i]; 1426 value(rv) *= tens[i];
1401 if (e1 &= ~15) { 1427 if (e1 &= ~15) {
1402 if (e1 > DBL_MAX_10_EXP) { 1428 if (e1 > DBL_MAX_10_EXP) {
1403 ovfl: 1429 ovfl:
1404 errno = ERANGE; 1430 errno = ERANGE;
1405#ifdef __STDC__ 1431#ifndef Bad_float_h
1406 rv = HUGE_VAL; 1432 value(rv) = HUGE_VAL;
1407#else 1433#else
1408 /* Can't trust HUGE_VAL */ 1434 /* Can't trust HUGE_VAL */
1409#ifdef IEEE_Arith 1435#ifdef IEEE_Arith
@@ -1421,10 +1447,10 @@ strtod
1421 if (e1 >>= 4) { 1447 if (e1 >>= 4) {
1422 for(j = 0; e1 > 1; j++, e1 >>= 1) 1448 for(j = 0; e1 > 1; j++, e1 >>= 1)
1423 if (e1 & 1) 1449 if (e1 & 1)
1424 rv *= bigtens[j]; 1450 value(rv) *= bigtens[j];
1425 /* The last multiplication could overflow. */ 1451 /* The last multiplication could overflow. */
1426 word0(rv) -= P*Exp_msk1; 1452 word0(rv) -= P*Exp_msk1;
1427 rv *= bigtens[j]; 1453 value(rv) *= bigtens[j];
1428 if ((z = word0(rv) & Exp_mask) 1454 if ((z = word0(rv) & Exp_mask)
1429 > Exp_msk1*(DBL_MAX_EXP+Bias-P)) 1455 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1430 goto ovfl; 1456 goto ovfl;
@@ -1443,23 +1469,23 @@ strtod
1443 else if (e1 < 0) { 1469 else if (e1 < 0) {
1444 e1 = -e1; 1470 e1 = -e1;
1445 if (i = e1 & 15) 1471 if (i = e1 & 15)
1446 rv /= tens[i]; 1472 value(rv) /= tens[i];
1447 if (e1 &= ~15) { 1473 if (e1 &= ~15) {
1448 e1 >>= 4; 1474 e1 >>= 4;
1449 if (e1 >= 1 << n_bigtens) 1475 if (e1 >= 1 << n_bigtens)
1450 goto undfl; 1476 goto undfl;
1451 for(j = 0; e1 > 1; j++, e1 >>= 1) 1477 for(j = 0; e1 > 1; j++, e1 >>= 1)
1452 if (e1 & 1) 1478 if (e1 & 1)
1453 rv *= tinytens[j]; 1479 value(rv) *= tinytens[j];
1454 /* The last multiplication could underflow. */ 1480 /* The last multiplication could underflow. */
1455 rv0 = rv; 1481 value(rv0) = value(rv);
1456 rv *= tinytens[j]; 1482 value(rv) *= tinytens[j];
1457 if (!rv) { 1483 if (!value(rv)) {
1458 rv = 2.*rv0; 1484 value(rv) = 2.*value(rv0);
1459 rv *= tinytens[j]; 1485 value(rv) *= tinytens[j];
1460 if (!rv) { 1486 if (!value(rv)) {
1461 undfl: 1487 undfl:
1462 rv = 0.; 1488 value(rv) = 0.;
1463 errno = ERANGE; 1489 errno = ERANGE;
1464 if (bd0) 1490 if (bd0)
1465 goto retfree; 1491 goto retfree;
@@ -1483,7 +1509,7 @@ strtod
1483 for(;;) { 1509 for(;;) {
1484 bd = Balloc(bd0->k); 1510 bd = Balloc(bd0->k);
1485 Bcopy(bd, bd0); 1511 Bcopy(bd, bd0);
1486 bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ 1512 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1487 bs = i2b(1); 1513 bs = i2b(1);
1488 1514
1489 if (e >= 0) { 1515 if (e >= 0) {
@@ -1595,12 +1621,12 @@ strtod
1595 break; 1621 break;
1596#endif 1622#endif
1597 if (dsign) 1623 if (dsign)
1598 rv += ulp(rv); 1624 value(rv) += ulp(value(rv));
1599#ifndef ROUND_BIASED 1625#ifndef ROUND_BIASED
1600 else { 1626 else {
1601 rv -= ulp(rv); 1627 value(rv) -= ulp(value(rv));
1602#ifndef Sudden_Underflow 1628#ifndef Sudden_Underflow
1603 if (!rv) 1629 if (!value(rv))
1604 goto undfl; 1630 goto undfl;
1605#endif 1631#endif
1606 } 1632 }
@@ -1651,10 +1677,10 @@ strtod
1651 /* Check for overflow */ 1677 /* Check for overflow */
1652 1678
1653 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { 1679 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1654 rv0 = rv; 1680 value(rv0) = value(rv);
1655 word0(rv) -= P*Exp_msk1; 1681 word0(rv) -= P*Exp_msk1;
1656 adj = aadj1 * ulp(rv); 1682 adj = aadj1 * ulp(value(rv));
1657 rv += adj; 1683 value(rv) += adj;
1658 if ((word0(rv) & Exp_mask) >= 1684 if ((word0(rv) & Exp_mask) >=
1659 Exp_msk1*(DBL_MAX_EXP+Bias-P)) { 1685 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1660 if (word0(rv0) == Big0 && word1(rv0) == Big1) 1686 if (word0(rv0) == Big0 && word1(rv0) == Big1)
@@ -1669,10 +1695,10 @@ strtod
1669 else { 1695 else {
1670#ifdef Sudden_Underflow 1696#ifdef Sudden_Underflow
1671 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { 1697 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1672 rv0 = rv; 1698 value(rv0) = value(rv);
1673 word0(rv) += P*Exp_msk1; 1699 word0(rv) += P*Exp_msk1;
1674 adj = aadj1 * ulp(rv); 1700 adj = aadj1 * ulp(value(rv));
1675 rv += adj; 1701 value(rv) += adj;
1676#ifdef IBM 1702#ifdef IBM
1677 if ((word0(rv) & Exp_mask) < P*Exp_msk1) 1703 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1678#else 1704#else
@@ -1690,8 +1716,8 @@ strtod
1690 word0(rv) -= P*Exp_msk1; 1716 word0(rv) -= P*Exp_msk1;
1691 } 1717 }
1692 else { 1718 else {
1693 adj = aadj1 * ulp(rv); 1719 adj = aadj1 * ulp(value(rv));
1694 rv += adj; 1720 value(rv) += adj;
1695 } 1721 }
1696#else 1722#else
1697 /* Compute adj so that the IEEE rounding rules will 1723 /* Compute adj so that the IEEE rounding rules will
@@ -1706,8 +1732,8 @@ strtod
1706 if (!dsign) 1732 if (!dsign)
1707 aadj1 = -aadj1; 1733 aadj1 = -aadj1;
1708 } 1734 }
1709 adj = aadj1 * ulp(rv); 1735 adj = aadj1 * ulp(value(rv));
1710 rv += adj; 1736 value(rv) += adj;
1711#endif 1737#endif
1712 } 1738 }
1713 z = word0(rv) & Exp_mask; 1739 z = word0(rv) & Exp_mask;
@@ -1738,7 +1764,7 @@ strtod
1738 ret: 1764 ret:
1739 if (se) 1765 if (se)
1740 *se = (char *)s; 1766 *se = (char *)s;
1741 return sign ? -rv : rv; 1767 return sign ? -value(rv) : value(rv);
1742 } 1768 }
1743 1769
1744 static int 1770 static int
@@ -1884,10 +1910,10 @@ quorem
1884 char * 1910 char *
1885__dtoa 1911__dtoa
1886#ifdef KR_headers 1912#ifdef KR_headers
1887 (d, mode, ndigits, decpt, sign, rve) 1913 (_d, mode, ndigits, decpt, sign, rve)
1888 double d; int mode, ndigits, *decpt, *sign; char **rve; 1914 double _d; int mode, ndigits, *decpt, *sign; char **rve;
1889#else 1915#else
1890 (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) 1916 (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1891#endif 1917#endif
1892{ 1918{
1893 /* Arguments ndigits, decpt, sign are similar to those 1919 /* Arguments ndigits, decpt, sign are similar to those
@@ -1933,11 +1959,13 @@ __dtoa
1933 ULong x; 1959 ULong x;
1934#endif 1960#endif
1935 Bigint *b, *b1, *delta, *mlo, *mhi, *S; 1961 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1936 double d2, ds, eps; 1962 double ds;
1937 char *s, *s0; 1963 char *s, *s0;
1938 static Bigint *result; 1964 static Bigint *result;
1939 static int result_k; 1965 static int result_k;
1966 _double d, d2, eps;
1940 1967
1968 value(d) = _d;
1941 if (result) { 1969 if (result) {
1942 result->k = result_k; 1970 result->k = result_k;
1943 result->maxwds = 1 << result_k; 1971 result->maxwds = 1 << result_k;
@@ -1964,7 +1992,7 @@ __dtoa
1964 *decpt = 9999; 1992 *decpt = 9999;
1965 s = 1993 s =
1966#ifdef IEEE_Arith 1994#ifdef IEEE_Arith
1967 !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" : 1995 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1968#endif 1996#endif
1969 "NaN"; 1997 "NaN";
1970 if (rve) 1998 if (rve)
@@ -1977,9 +2005,9 @@ __dtoa
1977 } 2005 }
1978#endif 2006#endif
1979#ifdef IBM 2007#ifdef IBM
1980 d += 0; /* normalize */ 2008 value(d) += 0; /* normalize */
1981#endif 2009#endif
1982 if (!d) { 2010 if (!value(d)) {
1983 *decpt = 1; 2011 *decpt = 1;
1984 s = "0"; 2012 s = "0";
1985 if (rve) 2013 if (rve)
@@ -1987,18 +2015,18 @@ __dtoa
1987 return s; 2015 return s;
1988 } 2016 }
1989 2017
1990 b = d2b(d, &be, &bbits); 2018 b = d2b(value(d), &be, &bbits);
1991#ifdef Sudden_Underflow 2019#ifdef Sudden_Underflow
1992 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); 2020 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1993#else 2021#else
1994 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { 2022 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1995#endif 2023#endif
1996 d2 = d; 2024 value(d2) = value(d);
1997 word0(d2) &= Frac_mask1; 2025 word0(d2) &= Frac_mask1;
1998 word0(d2) |= Exp_11; 2026 word0(d2) |= Exp_11;
1999#ifdef IBM 2027#ifdef IBM
2000 if (j = 11 - hi0bits(word0(d2) & Frac_mask)) 2028 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
2001 d2 /= 1 << j; 2029 value(d2) /= 1 << j;
2002#endif 2030#endif
2003 2031
2004 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 2032 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
@@ -2037,19 +2065,20 @@ __dtoa
2037 i = bbits + be + (Bias + (P-1) - 1); 2065 i = bbits + be + (Bias + (P-1) - 1);
2038 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 2066 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2039 : word1(d) << 32 - i; 2067 : word1(d) << 32 - i;
2040 d2 = x; 2068 value(d2) = x;
2041 word0(d2) -= 31*Exp_msk1; /* adjust exponent */ 2069 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2042 i -= (Bias + (P-1) - 1) + 1; 2070 i -= (Bias + (P-1) - 1) + 1;
2043 denorm = 1; 2071 denorm = 1;
2044 } 2072 }
2045#endif 2073#endif
2046 ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; 2074 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
2075 i*0.301029995663981;
2047 k = (int)ds; 2076 k = (int)ds;
2048 if (ds < 0. && ds != k) 2077 if (ds < 0. && ds != k)
2049 k--; /* want k = floor(ds) */ 2078 k--; /* want k = floor(ds) */
2050 k_check = 1; 2079 k_check = 1;
2051 if (k >= 0 && k <= Ten_pmax) { 2080 if (k >= 0 && k <= Ten_pmax) {
2052 if (d < tens[k]) 2081 if (value(d) < tens[k])
2053 k--; 2082 k--;
2054 k_check = 0; 2083 k_check = 0;
2055 } 2084 }
@@ -2116,7 +2145,7 @@ __dtoa
2116 /* Try to get by with floating-point arithmetic. */ 2145 /* Try to get by with floating-point arithmetic. */
2117 2146
2118 i = 0; 2147 i = 0;
2119 d2 = d; 2148 value(d2) = value(d);
2120 k0 = k; 2149 k0 = k;
2121 ilim0 = ilim; 2150 ilim0 = ilim;
2122 ieps = 2; /* conservative */ 2151 ieps = 2; /* conservative */
@@ -2126,7 +2155,7 @@ __dtoa
2126 if (j & Bletch) { 2155 if (j & Bletch) {
2127 /* prevent overflows */ 2156 /* prevent overflows */
2128 j &= Bletch - 1; 2157 j &= Bletch - 1;
2129 d /= bigtens[n_bigtens-1]; 2158 value(d) /= bigtens[n_bigtens-1];
2130 ieps++; 2159 ieps++;
2131 } 2160 }
2132 for(; j; j >>= 1, i++) 2161 for(; j; j >>= 1, i++)
@@ -2134,32 +2163,32 @@ __dtoa
2134 ieps++; 2163 ieps++;
2135 ds *= bigtens[i]; 2164 ds *= bigtens[i];
2136 } 2165 }
2137 d /= ds; 2166 value(d) /= ds;
2138 } 2167 }
2139 else if (j1 = -k) { 2168 else if (j1 = -k) {
2140 d *= tens[j1 & 0xf]; 2169 value(d) *= tens[j1 & 0xf];
2141 for(j = j1 >> 4; j; j >>= 1, i++) 2170 for(j = j1 >> 4; j; j >>= 1, i++)
2142 if (j & 1) { 2171 if (j & 1) {
2143 ieps++; 2172 ieps++;
2144 d *= bigtens[i]; 2173 value(d) *= bigtens[i];
2145 } 2174 }
2146 } 2175 }
2147 if (k_check && d < 1. && ilim > 0) { 2176 if (k_check && value(d) < 1. && ilim > 0) {
2148 if (ilim1 <= 0) 2177 if (ilim1 <= 0)
2149 goto fast_failed; 2178 goto fast_failed;
2150 ilim = ilim1; 2179 ilim = ilim1;
2151 k--; 2180 k--;
2152 d *= 10.; 2181 value(d) *= 10.;
2153 ieps++; 2182 ieps++;
2154 } 2183 }
2155 eps = ieps*d + 7.; 2184 value(eps) = ieps*value(d) + 7.;
2156 word0(eps) -= (P-1)*Exp_msk1; 2185 word0(eps) -= (P-1)*Exp_msk1;
2157 if (ilim == 0) { 2186 if (ilim == 0) {
2158 S = mhi = 0; 2187 S = mhi = 0;
2159 d -= 5.; 2188 value(d) -= 5.;
2160 if (d > eps) 2189 if (value(d) > value(eps))
2161 goto one_digit; 2190 goto one_digit;
2162 if (d < -eps) 2191 if (value(d) < -value(eps))
2163 goto no_digits; 2192 goto no_digits;
2164 goto fast_failed; 2193 goto fast_failed;
2165 } 2194 }
@@ -2168,33 +2197,33 @@ __dtoa
2168 /* Use Steele & White method of only 2197 /* Use Steele & White method of only
2169 * generating digits needed. 2198 * generating digits needed.
2170 */ 2199 */
2171 eps = 0.5/tens[ilim-1] - eps; 2200 value(eps) = 0.5/tens[ilim-1] - value(eps);
2172 for(i = 0;;) { 2201 for(i = 0;;) {
2173 L = d; 2202 L = value(d);
2174 d -= L; 2203 value(d) -= L;
2175 *s++ = '0' + (int)L; 2204 *s++ = '0' + (int)L;
2176 if (d < eps) 2205 if (value(d) < value(eps))
2177 goto ret1; 2206 goto ret1;
2178 if (1. - d < eps) 2207 if (1. - value(d) < value(eps))
2179 goto bump_up; 2208 goto bump_up;
2180 if (++i >= ilim) 2209 if (++i >= ilim)
2181 break; 2210 break;
2182 eps *= 10.; 2211 value(eps) *= 10.;
2183 d *= 10.; 2212 value(d) *= 10.;
2184 } 2213 }
2185 } 2214 }
2186 else { 2215 else {
2187#endif 2216#endif
2188 /* Generate ilim digits, then fix them up. */ 2217 /* Generate ilim digits, then fix them up. */
2189 eps *= tens[ilim-1]; 2218 value(eps) *= tens[ilim-1];
2190 for(i = 1;; i++, d *= 10.) { 2219 for(i = 1;; i++, value(d) *= 10.) {
2191 L = d; 2220 L = value(d);
2192 d -= L; 2221 value(d) -= L;
2193 *s++ = '0' + (int)L; 2222 *s++ = '0' + (int)L;
2194 if (i == ilim) { 2223 if (i == ilim) {
2195 if (d > 0.5 + eps) 2224 if (value(d) > 0.5 + value(eps))
2196 goto bump_up; 2225 goto bump_up;
2197 else if (d < 0.5 - eps) { 2226 else if (value(d) < 0.5 - value(eps)) {
2198 while(*--s == '0'); 2227 while(*--s == '0');
2199 s++; 2228 s++;
2200 goto ret1; 2229 goto ret1;
@@ -2207,7 +2236,7 @@ __dtoa
2207#endif 2236#endif
2208 fast_failed: 2237 fast_failed:
2209 s = s0; 2238 s = s0;
2210 d = d2; 2239 value(d) = value(d2);
2211 k = k0; 2240 k = k0;
2212 ilim = ilim0; 2241 ilim = ilim0;
2213 } 2242 }
@@ -2219,24 +2248,24 @@ __dtoa
2219 ds = tens[k]; 2248 ds = tens[k];
2220 if (ndigits < 0 && ilim <= 0) { 2249 if (ndigits < 0 && ilim <= 0) {
2221 S = mhi = 0; 2250 S = mhi = 0;
2222 if (ilim < 0 || d <= 5*ds) 2251 if (ilim < 0 || value(d) <= 5*ds)
2223 goto no_digits; 2252 goto no_digits;
2224 goto one_digit; 2253 goto one_digit;
2225 } 2254 }
2226 for(i = 1;; i++) { 2255 for(i = 1;; i++) {
2227 L = d / ds; 2256 L = value(d) / ds;
2228 d -= L*ds; 2257 value(d) -= L*ds;
2229#ifdef Check_FLT_ROUNDS 2258#ifdef Check_FLT_ROUNDS
2230 /* If FLT_ROUNDS == 2, L will usually be high by 1 */ 2259 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2231 if (d < 0) { 2260 if (value(d) < 0) {
2232 L--; 2261 L--;
2233 d += ds; 2262 value(d) += ds;
2234 } 2263 }
2235#endif 2264#endif
2236 *s++ = '0' + (int)L; 2265 *s++ = '0' + (int)L;
2237 if (i == ilim) { 2266 if (i == ilim) {
2238 d += d; 2267 value(d) += value(d);
2239 if (d > ds || d == ds && L & 1) { 2268 if (value(d) > ds || value(d) == ds && L & 1) {
2240 bump_up: 2269 bump_up:
2241 while(*--s == '9') 2270 while(*--s == '9')
2242 if (s == s0) { 2271 if (s == s0) {
@@ -2248,7 +2277,7 @@ __dtoa
2248 } 2277 }
2249 break; 2278 break;
2250 } 2279 }
2251 if (!(d *= 10.)) 2280 if (!(value(d) *= 10.))
2252 break; 2281 break;
2253 } 2282 }
2254 goto ret1; 2283 goto ret1;
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
index 808ba90165..b37f2cd725 100644
--- a/src/lib/libc/stdlib/strtol.3
+++ b/src/lib/libc/stdlib/strtol.3
@@ -33,49 +33,57 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtol.3 5.4 (Berkeley) 6/25/92 36.\" $OpenBSD: strtol.3,v 1.12 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: strtol.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 25, 1992 38.Dd June 25, 1992
40.Dt STRTOL 3 39.Dt STRTOL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strtol, strtoq 42.Nm strtol ,
44.Nd convert string value to a long or quad_t integer 43.Nm strtoll ,
44.Nm strtoq
45.Nd "convert string value to a long or long long integer"
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Fd #include <limits.h> 48.Fd #include <limits.h>
48.Ft long 49.Ft long
49.Fn strtol "char *nptr" "char **endptr" "int base" 50.Fn strtol "const char *nptr" "char **endptr" "int base"
50 51.Pp
52.Fd #include <stdlib.h>
53.Fd #include <limits.h>
54.Ft long long
55.Fn strtoll "const char *nptr" "char **endptr" "int base"
56.Pp
51.Fd #include <sys/types.h> 57.Fd #include <sys/types.h>
52.Fd #include <stdlib.h> 58.Fd #include <stdlib.h>
53.Fd #include <limits.h> 59.Fd #include <limits.h>
54.Ft quad_t 60.Ft quad_t
55.Fn strtoq "char *nptr" "char **endptr" "int base" 61.Fn strtoq "const char *nptr" "char **endptr" "int base"
56.Sh DESCRIPTION 62.Sh DESCRIPTION
57The 63The
58.Fn strtol 64.Fn strtol
59function 65function converts the string in
60converts the string in
61.Fa nptr 66.Fa nptr
62to a 67to a
63.Em long 68.Li long
64value. 69value.
65The 70The
66.Fn strtoq 71.Fn strtoll
67function 72function converts the string in
68converts the string in
69.Fa nptr 73.Fa nptr
70to a 74to a
71.Em quad_t 75.Li long long
72value. 76value.
77The
78.Fn strtoq
79function is a deprecated equivalent of
80.Fn strtoll
81and is provided for backwards compatibility with legacy programs.
73The conversion is done according to the given 82The conversion is done according to the given
74.Fa base , 83.Fa base ,
75which must be between 2 and 36 inclusive, 84which must be a number between 2 and 36 inclusive or the special value 0.
76or be the special value 0.
77.Pp 85.Pp
78The string may begin with an arbitrary amount of white space 86The string may begin with an arbitrary amount of whitespace
79(as determined by 87(as determined by
80.Xr isspace 3 ) 88.Xr isspace 3 )
81followed by a single optional 89followed by a single optional
@@ -85,25 +93,22 @@ or
85sign. 93sign.
86If 94If
87.Fa base 95.Fa base
88is zero or 16, 96is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 97.Ql 0x
91prefix, 98prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 99.Fa base
94is taken as 10 (decimal) unless the next character is 100is taken as 10 (decimal) unless the next character is
95.Ql 0 , 101.Ql 0 ,
96in which case it is taken as 8 (octal). 102in which case it is taken as 8 (octal).
97.Pp 103.Pp
98The remainder of the string is converted to a 104The remainder of the string is converted to a
99.Em long 105.Li long
100value in the obvious manner, 106value in the obvious manner,
101stopping at the first character which is not a valid digit 107stopping at the first character which is not a valid digit
102in the given base. 108in the given base.
103(In bases above 10, the letter 109(In bases above 10, the letter
104.Ql A 110.Ql A
105in either upper or lower case 111in either upper or lower case represents 10,
106represents 10,
107.Ql B 112.Ql B
108represents 11, and so forth, with 113represents 11, and so forth, with
109.Ql Z 114.Ql Z
@@ -111,7 +116,7 @@ representing 35.)
111.Pp 116.Pp
112If 117If
113.Fa endptr 118.Fa endptr
114is non nil, 119is non-null,
115.Fn strtol 120.Fn strtol
116stores the address of the first invalid character in 121stores the address of the first invalid character in
117.Fa *endptr . 122.Fa *endptr .
@@ -133,8 +138,7 @@ on return, the entire string was valid.)
133.Sh RETURN VALUES 138.Sh RETURN VALUES
134The 139The
135.Fn strtol 140.Fn strtol
136function 141function returns the result of the conversion,
137returns the result of the conversion,
138unless the value would underflow or overflow. 142unless the value would underflow or overflow.
139If an underflow occurs, 143If an underflow occurs,
140.Fn strtol 144.Fn strtol
@@ -148,6 +152,76 @@ In both cases,
148.Va errno 152.Va errno
149is set to 153is set to
150.Er ERANGE . 154.Er ERANGE .
155.Pp
156The
157.Fn strtoll
158function has identical return values except that
159.Dv LLONG_MIN
160and
161.Dv LLONG_MAX
162are used to indicate underflow and overflow respectively.
163.Sh EXAMPLES
164Ensuring that a string is a valid number (i.e., in range and containing no
165trailing characters) requires clearing
166.Va errno
167beforehand explicitly since
168.Va errno
169is not changed on a successful call to
170.Fn strtol ,
171and the return value of
172.Fn strtol
173cannot be used unambiguously to signal an error:
174.Bd -literal -offset indent
175char *ep;
176long lval;
177
178\&...
179
180errno = 0;
181lval = strtol(buf, &ep, 10);
182if (buf[0] == '\e0' || *ep != '\e0')
183 goto not_a_number;
184if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
185 goto out_of_range;
186.Ed
187.Pp
188This example will accept
189.Dq 12
190but not
191.Dq 12foo
192or
193.Dq 12\en .
194If trailing whitespace is acceptable, further checks must be done on
195.Va *ep ;
196alternately, use
197.Xr sscanf 3 .
198.Pp
199If
200.Fn strtol
201is being used instead of
202.Xr atoi 3 ,
203error checking is further complicated because the desired return value is an
204.Li int
205rather than a
206.Li long ;
207however, on some architectures integers and long integers are the same size.
208Thus the following is necessary:
209.Bd -literal -offset indent
210char *ep;
211int ival;
212long lval;
213
214\&...
215
216errno = 0;
217lval = strtol(buf, &ep, 10);
218if (buf[0] == '\e0' || *ep != '\e0')
219 goto not_a_number;
220if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
221 (lval > INT_MAX || lval < INT_MIN))
222 goto out_of_range;
223ival = lval;
224.Ed
151.Sh ERRORS 225.Sh ERRORS
152.Bl -tag -width Er 226.Bl -tag -width Er
153.It Bq Er ERANGE 227.It Bq Er ERANGE
@@ -157,13 +231,21 @@ The given string was out of range; the value converted has been clamped.
157.Xr atof 3 , 231.Xr atof 3 ,
158.Xr atoi 3 , 232.Xr atoi 3 ,
159.Xr atol 3 , 233.Xr atol 3 ,
234.Xr atoll 3 ,
235.Xr sscanf 3 ,
160.Xr strtod 3 , 236.Xr strtod 3 ,
161.Xr strtoul 3 237.Xr strtoul 3
162.Sh STANDARDS 238.Sh STANDARDS
163The 239The
164.Fn strtol 240.Fn strtol
165function 241and
166conforms to 242.Fn strtoll
167.St -ansiC . 243functions conform to
244.St -ansiC-99 .
245The
246.Fn strtoq
247function is a
248.Bx
249extension and is provided for backwards compatibility with legacy programs.
168.Sh BUGS 250.Sh BUGS
169Ignores the current locale. 251Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
index 6f374abd5f..e4ad557fd5 100644
--- a/src/lib/libc/stdlib/strtol.c
+++ b/src/lib/libc/stdlib/strtol.c
@@ -32,13 +32,12 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: strtol.c,v 1.4 1996/08/19 08:33:51 tholo Exp $";
36static char *rcsid = "$Id: strtol.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <limits.h>
40#include <ctype.h> 38#include <ctype.h>
41#include <errno.h> 39#include <errno.h>
40#include <limits.h>
42#include <stdlib.h> 41#include <stdlib.h>
43 42
44 43
@@ -54,25 +53,28 @@ strtol(nptr, endptr, base)
54 char **endptr; 53 char **endptr;
55 register int base; 54 register int base;
56{ 55{
57 register const char *s = nptr; 56 register const char *s;
58 register unsigned long acc; 57 register long acc, cutoff;
59 register int c; 58 register int c;
60 register unsigned long cutoff; 59 register int neg, any, cutlim;
61 register int neg = 0, any, cutlim;
62 60
63 /* 61 /*
64 * Skip white space and pick up leading +/- sign if any. 62 * Skip white space and pick up leading +/- sign if any.
65 * If base is 0, allow 0x for hex and 0 for octal, else 63 * If base is 0, allow 0x for hex and 0 for octal, else
66 * assume decimal; if base is already 16, allow 0x. 64 * assume decimal; if base is already 16, allow 0x.
67 */ 65 */
66 s = nptr;
68 do { 67 do {
69 c = *s++; 68 c = (unsigned char) *s++;
70 } while (isspace(c)); 69 } while (isspace(c));
71 if (c == '-') { 70 if (c == '-') {
72 neg = 1; 71 neg = 1;
73 c = *s++; 72 c = *s++;
74 } else if (c == '+') 73 } else {
75 c = *s++; 74 neg = 0;
75 if (c == '+')
76 c = *s++;
77 }
76 if ((base == 0 || base == 16) && 78 if ((base == 0 || base == 16) &&
77 c == '0' && (*s == 'x' || *s == 'X')) { 79 c == '0' && (*s == 'x' || *s == 'X')) {
78 c = s[1]; 80 c = s[1];
@@ -99,10 +101,17 @@ strtol(nptr, endptr, base)
99 * Set any if any `digits' consumed; make it negative to indicate 101 * Set any if any `digits' consumed; make it negative to indicate
100 * overflow. 102 * overflow.
101 */ 103 */
102 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 104 cutoff = neg ? LONG_MIN : LONG_MAX;
103 cutlim = cutoff % (unsigned long)base; 105 cutlim = cutoff % base;
104 cutoff /= (unsigned long)base; 106 cutoff /= base;
105 for (acc = 0, any = 0;; c = *s++) { 107 if (neg) {
108 if (cutlim > 0) {
109 cutlim -= base;
110 cutoff += 1;
111 }
112 cutlim = -cutlim;
113 }
114 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
106 if (isdigit(c)) 115 if (isdigit(c))
107 c -= '0'; 116 c -= '0';
108 else if (isalpha(c)) 117 else if (isalpha(c))
@@ -111,19 +120,30 @@ strtol(nptr, endptr, base)
111 break; 120 break;
112 if (c >= base) 121 if (c >= base)
113 break; 122 break;
114 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 123 if (any < 0)
115 any = -1; 124 continue;
116 else { 125 if (neg) {
117 any = 1; 126 if (acc < cutoff || acc == cutoff && c > cutlim) {
118 acc *= base; 127 any = -1;
119 acc += c; 128 acc = LONG_MIN;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc -= c;
134 }
135 } else {
136 if (acc > cutoff || acc == cutoff && c > cutlim) {
137 any = -1;
138 acc = LONG_MAX;
139 errno = ERANGE;
140 } else {
141 any = 1;
142 acc *= base;
143 acc += c;
144 }
120 } 145 }
121 } 146 }
122 if (any < 0) {
123 acc = neg ? LONG_MIN : LONG_MAX;
124 errno = ERANGE;
125 } else if (neg)
126 acc = -acc;
127 if (endptr != 0) 147 if (endptr != 0)
128 *endptr = (char *) (any ? s - 1 : nptr); 148 *endptr = (char *) (any ? s - 1 : nptr);
129 return (acc); 149 return (acc);
diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoll.c
index fc559e9d7f..b0eb6d198c 100644
--- a/src/lib/libc/stdlib/strtoq.c
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -32,33 +32,32 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92"; 35static const char rcsid[] = "$OpenBSD: strtoll.c,v 1.1 2002/06/29 00:20:11 millert Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39 39
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 40#include <ctype.h>
41#include <errno.h>
42#include <limits.h>
43#include <stdlib.h> 43#include <stdlib.h>
44 44
45/* 45/*
46 * Convert a string to a quad integer. 46 * Convert a string to a long long.
47 * 47 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 48 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 49 * alphabets and digits are each contiguous.
50 */ 50 */
51quad_t 51long long
52strtoq(nptr, endptr, base) 52strtoll(nptr, endptr, base)
53 const char *nptr; 53 const char *nptr;
54 char **endptr; 54 char **endptr;
55 register int base; 55 int base;
56{ 56{
57 register const char *s; 57 const char *s;
58 register u_quad_t acc; 58 long long acc, cutoff;
59 register int c; 59 int c;
60 register u_quad_t qbase, cutoff; 60 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 61
63 /* 62 /*
64 * Skip white space and pick up leading +/- sign if any. 63 * Skip white space and pick up leading +/- sign if any.
@@ -67,7 +66,7 @@ strtoq(nptr, endptr, base)
67 */ 66 */
68 s = nptr; 67 s = nptr;
69 do { 68 do {
70 c = *s++; 69 c = (unsigned char) *s++;
71 } while (isspace(c)); 70 } while (isspace(c));
72 if (c == '-') { 71 if (c == '-') {
73 neg = 1; 72 neg = 1;
@@ -93,7 +92,7 @@ strtoq(nptr, endptr, base)
93 * followed by a legal input character, is too big. One that 92 * followed by a legal input character, is too big. One that
94 * is equal to this value may be valid or not; the limit 93 * is equal to this value may be valid or not; the limit
95 * between valid and invalid numbers is then based on the last 94 * between valid and invalid numbers is then based on the last
96 * digit. For instance, if the range for quads is 95 * digit. For instance, if the range for long longs is
97 * [-9223372036854775808..9223372036854775807] and the input base 96 * [-9223372036854775808..9223372036854775807] and the input base
98 * is 10, cutoff will be set to 922337203685477580 and cutlim to 97 * is 10, cutoff will be set to 922337203685477580 and cutlim to
99 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 98 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
@@ -104,11 +103,17 @@ strtoq(nptr, endptr, base)
104 * Set any if any `digits' consumed; make it negative to indicate 103 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow. 104 * overflow.
106 */ 105 */
107 qbase = (unsigned)base; 106 cutoff = neg ? LLONG_MIN : LLONG_MAX;
108 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 107 cutlim = cutoff % base;
109 cutlim = cutoff % qbase; 108 cutoff /= base;
110 cutoff /= qbase; 109 if (neg) {
111 for (acc = 0, any = 0;; c = *s++) { 110 if (cutlim > 0) {
111 cutlim -= base;
112 cutoff += 1;
113 }
114 cutlim = -cutlim;
115 }
116 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
112 if (isdigit(c)) 117 if (isdigit(c))
113 c -= '0'; 118 c -= '0';
114 else if (isalpha(c)) 119 else if (isalpha(c))
@@ -117,20 +122,45 @@ strtoq(nptr, endptr, base)
117 break; 122 break;
118 if (c >= base) 123 if (c >= base)
119 break; 124 break;
120 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 125 if (any < 0)
121 any = -1; 126 continue;
122 else { 127 if (neg) {
123 any = 1; 128 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
124 acc *= qbase; 129 any = -1;
125 acc += c; 130 acc = LLONG_MIN;
131 errno = ERANGE;
132 } else {
133 any = 1;
134 acc *= base;
135 acc -= c;
136 }
137 } else {
138 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
139 any = -1;
140 acc = LLONG_MAX;
141 errno = ERANGE;
142 } else {
143 any = 1;
144 acc *= base;
145 acc += c;
146 }
126 } 147 }
127 } 148 }
128 if (any < 0) {
129 acc = neg ? QUAD_MIN : QUAD_MAX;
130 errno = ERANGE;
131 } else if (neg)
132 acc = -acc;
133 if (endptr != 0) 149 if (endptr != 0)
134 *endptr = (char *) (any ? s - 1 : nptr); 150 *endptr = (char *) (any ? s - 1 : nptr);
135 return (acc); 151 return (acc);
136} 152}
153
154#ifdef __weak_alias
155__weak_alias(strtoq, strtoll);
156#else
157quad_t
158strtoq(nptr, endptr, base)
159 const char *nptr;
160 char **endptr;
161 int base;
162{
163
164 return ((quad_t)strtoll(nptr, endptr, base);
165}
166#endif
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
index db551b0141..39de7e0656 100644
--- a/src/lib/libc/stdlib/strtoul.3
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -33,21 +33,27 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtoul.3 5.4 (Berkeley) 6/25/92 36.\" $OpenBSD: strtoul.3,v 1.14 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: strtoul.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 37.\"
39.Dd June 25, 1992 38.Dd June 25, 1992
40.Dt STRTOUL 3 39.Dt STRTOUL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strtoul, strtouq 42.Nm strtoul ,
44.Nd convert a string to an unsigned long or uquad_t integer 43.Nm strtoull ,
44.Nm strtouq
45.Nd "convert a string to an unsigned long or unsigned long long integer"
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Fd #include <limits.h> 48.Fd #include <limits.h>
48.Ft unsigned long 49.Ft unsigned long
49.Fn strtoul "const char *nptr" "char **endptr" "int base" 50.Fn strtoul "const char *nptr" "char **endptr" "int base"
50 51.Pp
52.Fd #include <stdlib.h>
53.Fd #include <limits.h>
54.Ft unsigned long long
55.Fn strtoull "const char *nptr" "char **endptr" "int base"
56.Pp
51.Fd #include <sys/types.h> 57.Fd #include <sys/types.h>
52.Fd #include <stdlib.h> 58.Fd #include <stdlib.h>
53.Fd #include <limits.h> 59.Fd #include <limits.h>
@@ -56,26 +62,34 @@
56.Sh DESCRIPTION 62.Sh DESCRIPTION
57The 63The
58.Fn strtoul 64.Fn strtoul
59function 65function converts the string in
60converts the string in
61.Fa nptr 66.Fa nptr
62to an 67to an
63.Em unsigned long 68.Li unsigned long
64value. 69value.
65The 70The
66.Fn strtouq 71.Fn strtoull
67function 72function converts the string in
68converts the string in
69.Fa nptr 73.Fa nptr
70to a 74to an
71.Em u_quad_t 75.Li unsigned long long
72value. 76value.
77The
78.Fn strtouq
79function is a deprecated equivalent of
80.Fn strtoull
81and is provided for backwards compatibility with legacy programs.
73The conversion is done according to the given 82The conversion is done according to the given
74.Fa base , 83.Fa base ,
75which must be between 2 and 36 inclusive, 84which must be a number between 2 and 36 inclusive
76or be the special value 0. 85or the special value 0.
86If the string in
87.Fa nptr
88represents a negative number, it will be converted to its unsigned equivalent.
89This behavior is consistent with what happens when a signed integer type is
90cast to its unsigned counterpart.
77.Pp 91.Pp
78The string may begin with an arbitrary amount of white space 92The string may begin with an arbitrary amount of whitespace
79(as determined by 93(as determined by
80.Xr isspace 3 ) 94.Xr isspace 3 )
81followed by a single optional 95followed by a single optional
@@ -85,26 +99,22 @@ or
85sign. 99sign.
86If 100If
87.Fa base 101.Fa base
88is zero or 16, 102is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 103.Ql 0x
91prefix, 104prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 105.Fa base
94is taken as 10 (decimal) unless the next character is 106is taken as 10 (decimal) unless the next character is
95.Ql 0 , 107.Ql 0 ,
96in which case it is taken as 8 (octal). 108in which case it is taken as 8 (octal).
97.Pp 109.Pp
98The remainder of the string is converted to an 110The remainder of the string is converted to an
99.Em unsigned long 111.Li unsigned long
100value in the obvious manner, 112value in the obvious manner, stopping at the end of the string
101stopping at the end of the string
102or at the first character that does not produce a valid digit 113or at the first character that does not produce a valid digit
103in the given base. 114in the given base.
104(In bases above 10, the letter 115(In bases above 10, the letter
105.Ql A 116.Ql A
106in either upper or lower case 117in either upper or lower case represents 10,
107represents 10,
108.Ql B 118.Ql B
109represents 11, and so forth, with 119represents 11, and so forth, with
110.Ql Z 120.Ql Z
@@ -112,7 +122,7 @@ representing 35.)
112.Pp 122.Pp
113If 123If
114.Fa endptr 124.Fa endptr
115is non nil, 125is non-null,
116.Fn strtoul 126.Fn strtoul
117stores the address of the first invalid character in 127stores the address of the first invalid character in
118.Fa *endptr . 128.Fa *endptr .
@@ -134,12 +144,18 @@ on return, the entire string was valid.)
134.Sh RETURN VALUES 144.Sh RETURN VALUES
135The 145The
136.Fn strtoul 146.Fn strtoul
137function 147function returns the result of the conversion,
138returns either the result of the conversion 148unless the value would overflow, in which case
139or, if there was a leading minus sign, 149.Dv ULONG_MAX
140the negation of the result of the conversion, 150is returned and
141unless the original (non-negated) value would overflow; 151.Va errno
142in the latter case, 152is set to
153.Er ERANGE .
154If there was a leading minus sign,
155.Fn strtoul
156returns the (unsigned) negation of the absolute value of the number, unless
157the absolute value would overflow.
158In this case,
143.Fn strtoul 159.Fn strtoul
144returns 160returns
145.Dv ULONG_MAX 161.Dv ULONG_MAX
@@ -147,18 +163,73 @@ and sets the global variable
147.Va errno 163.Va errno
148to 164to
149.Er ERANGE . 165.Er ERANGE .
166.Pp
167The
168.Fn strtoull
169function has identical return values except that
170.Dv ULLONG_MAX
171is used to indicate overflow.
172.Pp
173There is no way to determine if
174.Fn strtoul
175has processed a negative number (and returned an unsigned value) short of
176examining the string in
177.Fa nptr
178directly.
179.Sh EXAMPLES
180Ensuring that a string is a valid number (i.e., in range and containing no
181trailing characters) requires clearing
182.Va errno
183beforehand explicitly since
184.Va errno
185is not changed on a successful call to
186.Fn strtoul ,
187and the return value of
188.Fn strtoul
189cannot be used unambiguously to signal an error:
190.Bd -literal -offset indent
191char *ep;
192unsigned long ulval;
193
194\&...
195
196errno = 0;
197ulval = strtoul(buf, &ep, 10);
198if (buf[0] == '\e0' || *ep != '\e0')
199 goto not_a_number;
200if (errno == ERANGE && ulval == ULONG_MAX)
201 goto out_of_range;
202.Ed
203.Pp
204This example will accept
205.Dq 12
206but not
207.Dq 12foo
208or
209.Dq 12\en .
210If trailing whitespace is acceptable, further checks must be done on
211.Va *ep ;
212alternately, use
213.Xr sscanf 3 .
150.Sh ERRORS 214.Sh ERRORS
151.Bl -tag -width Er 215.Bl -tag -width Er
152.It Bq Er ERANGE 216.It Bq Er ERANGE
153The given string was out of range; the value converted has been clamped. 217The given string was out of range; the value converted has been clamped.
154.El 218.El
155.Sh SEE ALSO 219.Sh SEE ALSO
220.Xr sscanf 3 ,
156.Xr strtol 3 221.Xr strtol 3
157.Sh STANDARDS 222.Sh STANDARDS
158The 223The
159.Fn strtoul 224.Fn strtoul
160function 225and
161conforms to 226.Fn strtoull
162.St -ansiC . 227functions conform to
228.St -ansiC-99 .
229The
230.Fn strtouq
231function is a
232.Bx
233extension and is provided for backwards compatibility with legacy programs.
163.Sh BUGS 234.Sh BUGS
164Ignores the current locale. 235Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
index 00f7210fa1..d3b363fa04 100644
--- a/src/lib/libc/stdlib/strtoul.c
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -32,13 +32,12 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: strtoul.c,v 1.4 1996/08/19 08:33:52 tholo Exp $";
36static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <limits.h>
40#include <ctype.h> 38#include <ctype.h>
41#include <errno.h> 39#include <errno.h>
40#include <limits.h>
42#include <stdlib.h> 41#include <stdlib.h>
43 42
44/* 43/*
@@ -53,23 +52,26 @@ strtoul(nptr, endptr, base)
53 char **endptr; 52 char **endptr;
54 register int base; 53 register int base;
55{ 54{
56 register const char *s = nptr; 55 register const char *s;
57 register unsigned long acc; 56 register unsigned long acc, cutoff;
58 register int c; 57 register int c;
59 register unsigned long cutoff; 58 register int neg, any, cutlim;
60 register int neg = 0, any, cutlim;
61 59
62 /* 60 /*
63 * See strtol for comments as to the logic used. 61 * See strtol for comments as to the logic used.
64 */ 62 */
63 s = nptr;
65 do { 64 do {
66 c = *s++; 65 c = (unsigned char) *s++;
67 } while (isspace(c)); 66 } while (isspace(c));
68 if (c == '-') { 67 if (c == '-') {
69 neg = 1; 68 neg = 1;
70 c = *s++; 69 c = *s++;
71 } else if (c == '+') 70 } else {
72 c = *s++; 71 neg = 0;
72 if (c == '+')
73 c = *s++;
74 }
73 if ((base == 0 || base == 16) && 75 if ((base == 0 || base == 16) &&
74 c == '0' && (*s == 'x' || *s == 'X')) { 76 c == '0' && (*s == 'x' || *s == 'X')) {
75 c = s[1]; 77 c = s[1];
@@ -78,9 +80,10 @@ strtoul(nptr, endptr, base)
78 } 80 }
79 if (base == 0) 81 if (base == 0)
80 base = c == '0' ? 8 : 10; 82 base = c == '0' ? 8 : 10;
81 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 83
82 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 84 cutoff = ULONG_MAX / (unsigned long)base;
83 for (acc = 0, any = 0;; c = *s++) { 85 cutlim = ULONG_MAX % (unsigned long)base;
86 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
84 if (isdigit(c)) 87 if (isdigit(c))
85 c -= '0'; 88 c -= '0';
86 else if (isalpha(c)) 89 else if (isalpha(c))
@@ -89,18 +92,19 @@ strtoul(nptr, endptr, base)
89 break; 92 break;
90 if (c >= base) 93 if (c >= base)
91 break; 94 break;
92 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 95 if (any < 0)
96 continue;
97 if (acc > cutoff || acc == cutoff && c > cutlim) {
93 any = -1; 98 any = -1;
94 else { 99 acc = ULONG_MAX;
100 errno = ERANGE;
101 } else {
95 any = 1; 102 any = 1;
96 acc *= base; 103 acc *= (unsigned long)base;
97 acc += c; 104 acc += c;
98 } 105 }
99 } 106 }
100 if (any < 0) { 107 if (neg && any > 0)
101 acc = ULONG_MAX;
102 errno = ERANGE;
103 } else if (neg)
104 acc = -acc; 108 acc = -acc;
105 if (endptr != 0) 109 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr); 110 *endptr = (char *) (any ? s - 1 : nptr);
diff --git a/src/lib/libc/stdlib/strtouq.c b/src/lib/libc/stdlib/strtoull.c
index cc647d8d28..7b4dd56c01 100644
--- a/src/lib/libc/stdlib/strtouq.c
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -32,40 +32,39 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 6/26/92"; 35static const char rcsid[] = "$OpenBSD: strtoull.c,v 1.1 2002/06/29 00:20:11 millert Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39 39
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 40#include <ctype.h>
41#include <errno.h>
42#include <limits.h>
43#include <stdlib.h> 43#include <stdlib.h>
44 44
45/* 45/*
46 * Convert a string to an unsigned quad integer. 46 * Convert a string to an unsigned long long.
47 * 47 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 48 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 49 * alphabets and digits are each contiguous.
50 */ 50 */
51u_quad_t 51unsigned long long
52strtouq(nptr, endptr, base) 52strtoull(nptr, endptr, base)
53 const char *nptr; 53 const char *nptr;
54 char **endptr; 54 char **endptr;
55 register int base; 55 int base;
56{ 56{
57 register const char *s = nptr; 57 const char *s;
58 register u_quad_t acc; 58 unsigned long long acc, cutoff;
59 register int c; 59 int c;
60 register u_quad_t qbase, cutoff; 60 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 61
63 /* 62 /*
64 * See strtoq for comments as to the logic used. 63 * See strtoq for comments as to the logic used.
65 */ 64 */
66 s = nptr; 65 s = nptr;
67 do { 66 do {
68 c = *s++; 67 c = (unsigned char) *s++;
69 } while (isspace(c)); 68 } while (isspace(c));
70 if (c == '-') { 69 if (c == '-') {
71 neg = 1; 70 neg = 1;
@@ -83,10 +82,10 @@ strtouq(nptr, endptr, base)
83 } 82 }
84 if (base == 0) 83 if (base == 0)
85 base = c == '0' ? 8 : 10; 84 base = c == '0' ? 8 : 10;
86 qbase = (unsigned)base; 85
87 cutoff = (u_quad_t)UQUAD_MAX / qbase; 86 cutoff = ULLONG_MAX / (unsigned long long)base;
88 cutlim = (u_quad_t)UQUAD_MAX % qbase; 87 cutlim = ULLONG_MAX % (unsigned long long)base;
89 for (acc = 0, any = 0;; c = *s++) { 88 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
90 if (isdigit(c)) 89 if (isdigit(c))
91 c -= '0'; 90 c -= '0';
92 else if (isalpha(c)) 91 else if (isalpha(c))
@@ -95,20 +94,35 @@ strtouq(nptr, endptr, base)
95 break; 94 break;
96 if (c >= base) 95 if (c >= base)
97 break; 96 break;
98 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 97 if (any < 0)
98 continue;
99 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
99 any = -1; 100 any = -1;
100 else { 101 acc = ULLONG_MAX;
102 errno = ERANGE;
103 } else {
101 any = 1; 104 any = 1;
102 acc *= qbase; 105 acc *= (unsigned long long)base;
103 acc += c; 106 acc += c;
104 } 107 }
105 } 108 }
106 if (any < 0) { 109 if (neg && any > 0)
107 acc = UQUAD_MAX;
108 errno = ERANGE;
109 } else if (neg)
110 acc = -acc; 110 acc = -acc;
111 if (endptr != 0) 111 if (endptr != 0)
112 *endptr = (char *) (any ? s - 1 : nptr); 112 *endptr = (char *) (any ? s - 1 : nptr);
113 return (acc); 113 return (acc);
114} 114}
115
116#ifdef __weak_alias
117__weak_alias(strtouq, strtoull);
118#else
119u_quad_t
120strtouq(nptr, endptr, base)
121 const char *nptr;
122 char **endptr;
123 int base;
124{
125
126 return ((u_quad_t)strtoull(nptr, endptr, base);
127}
128#endif
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
index 520f51db0a..83c6de80e3 100644
--- a/src/lib/libc/stdlib/system.3
+++ b/src/lib/libc/stdlib/system.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)system.3 6.5 (Berkeley) 6/29/91 36.\" $OpenBSD: system.3,v 1.8 2000/10/06 04:17:51 aaron Exp $
37.\" $Id: system.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt SYSTEM 3 39.Dt SYSTEM 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn system 50.Fn system
52function 51function hands the argument
53hands the argument
54.Fa string 52.Fa string
55to the command interpreter 53to the command interpreter
56.Xr sh 1 . 54.Xr sh 1 .
@@ -64,36 +62,42 @@ and blocking
64.Pp 62.Pp
65If 63If
66.Fa string 64.Fa string
67is a 65is
68.Dv NULL 66.Dv NULL ,
69pointer,
70.Fn system 67.Fn system
71will return non-zero. 68will return non-zero.
72Otherwise, 69Otherwise,
73.Fn system 70.Fn system
74returns the termination status of the shell in the format specified by 71returns the termination status of the shell in the format specified by
75.Xr waitpid 3 . 72.Xr waitpid 2 .
76.Sh RETURN VALUES 73.Sh RETURN VALUES
77If a child process cannot be created, or the termination status of 74If a child process cannot be created, or the termination status of
78the shell cannot be obtained, 75the shell cannot be obtained,
79.Fn system 76.Fn system
80returns -1 and sets 77returns \-1 and sets
81.Va errno 78.Va errno
82to indicate the error. 79to indicate the error.
83If execution of the shell fails, 80If execution of the shell fails,
84.Fn system 81.Fn system
85returns the termination status for a program that terminates with a call of 82returns the termination status for a program that terminates with a call of
86.Fn exit 127 . 83.Fn exit 127 .
87.Sh SEE ALSO 84.Sh SEE ALSO
88.Xr sh 1 , 85.Xr sh 1 ,
89.Xr execve 2 , 86.Xr execve 2 ,
90.Xr popen 3 , 87.Xr waitpid 2 ,
91.Xr waitpid 3 , 88.Xr popen 3
92.Sh STANDARDS 89.Sh STANDARDS
93The 90The
94.Fn system 91.Fn system
95function 92function conforms to
96conforms to 93.St -ansiC
97.St -ansiC
98and 94and
99.St -1003.2-92 . 95.St -p1003.2-92 .
96.Sh CAVEATS
97Never supply the
98.Fn system
99function with a command containing any part of an unsanitized user-supplied
100string.
101Shell meta-characters present will be honored by the
102.Xr sh 1
103command interpreter.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
index c2f39325f6..636a9ebdff 100644
--- a/src/lib/libc/stdlib/system.c
+++ b/src/lib/libc/stdlib/system.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)system.c 5.10 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: system.c,v 1.5 2002/05/26 09:29:02 deraadt Exp $";
36static char *rcsid = "$Id: system.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
@@ -51,20 +50,24 @@ system(command)
51{ 50{
52 pid_t pid; 51 pid_t pid;
53 sig_t intsave, quitsave; 52 sig_t intsave, quitsave;
54 int omask; 53 sigset_t mask, omask;
55 int pstat; 54 int pstat;
56 char *argp[] = {"sh", "-c", (char *) command, NULL}; 55 char *argp[] = {"sh", "-c", NULL, NULL};
57 56
58 if (!command) /* just checking... */ 57 if (!command) /* just checking... */
59 return(1); 58 return(1);
60 59
61 omask = sigblock(sigmask(SIGCHLD)); 60 argp[2] = (char *)command;
62 switch(pid = vfork()) { 61
62 sigemptyset(&mask);
63 sigaddset(&mask, SIGCHLD);
64 sigprocmask(SIG_BLOCK, &mask, &omask);
65 switch (pid = vfork()) {
63 case -1: /* error */ 66 case -1: /* error */
64 (void)sigsetmask(omask); 67 sigprocmask(SIG_SETMASK, &omask, NULL);
65 return(-1); 68 return(-1);
66 case 0: /* child */ 69 case 0: /* child */
67 (void)sigsetmask(omask); 70 sigprocmask(SIG_SETMASK, &omask, NULL);
68 execve(_PATH_BSHELL, argp, environ); 71 execve(_PATH_BSHELL, argp, environ);
69 _exit(127); 72 _exit(127);
70 } 73 }
@@ -72,8 +75,8 @@ system(command)
72 intsave = signal(SIGINT, SIG_IGN); 75 intsave = signal(SIGINT, SIG_IGN);
73 quitsave = signal(SIGQUIT, SIG_IGN); 76 quitsave = signal(SIGQUIT, SIG_IGN);
74 pid = waitpid(pid, (int *)&pstat, 0); 77 pid = waitpid(pid, (int *)&pstat, 0);
75 (void)sigsetmask(omask); 78 sigprocmask(SIG_SETMASK, &omask, NULL);
76 (void)signal(SIGINT, intsave); 79 (void)signal(SIGINT, intsave);
77 (void)signal(SIGQUIT, quitsave); 80 (void)signal(SIGQUIT, quitsave);
78 return(pid == -1 ? -1 : pstat); 81 return (pid == -1 ? -1 : pstat);
79} 82}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..5c3b8c17f5
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12#include <search.h>
13
14typedef struct node_t
15{
16 char *key;
17 struct node_t *llink, *rlink;
18} node;
19
20/* find a node, or return 0 */
21void *
22tfind(vkey, vrootp, compar)
23 const void *vkey; /* key to be found */
24 void *const *vrootp; /* address of the tree root */
25 int (*compar)(const void *, const void *);
26{
27 char *key = (char *)vkey;
28 node **rootp = (node **)vrootp;
29
30 if (rootp == (struct node_t **)0)
31 return ((struct node_t *)0);
32 while (*rootp != (struct node_t *)0) { /* T1: */
33 int r;
34 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
35 return (*rootp); /* key found */
36 rootp = (r < 0) ?
37 &(*rootp)->llink : /* T3: follow left branch */
38 &(*rootp)->rlink; /* T4: follow right branch */
39 }
40 return (node *)0;
41}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000000..b000a0a8b1
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,127 @@
1.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. The name of the author may not be used to endorse or promote products
13.\" derived from this software without specific prior written permission.
14.\"
15.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.\"
26.\" $OpenBSD: tsearch.3,v 1.9 2000/08/09 15:51:21 aaron Exp $
27.\"
28.Dd June 15, 1997
29.Dt TSEARCH 3
30.Os
31.Sh NAME
32.Nm tsearch ,
33.Nm tfind ,
34.Nm tdelete ,
35.Nm twalk
36.Nd manipulate binary search trees
37.Sh SYNOPSIS
38.Fd #include <search.h>
39.Ft void *
40.Fn tdelete "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
41.Ft void *
42.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)"
43.Ft void *
44.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
45.Ft void
46.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
47.Sh DESCRIPTION
48The
49.Fn tdelete ,
50.Fn tfind ,
51.Fn tsearch ,
52and
53.Fn twalk
54functions manage binary search trees based on algorithms T and D
55from Knuth (6.2.2).
56The comparison function passed in by
57the user has the same style of return values as
58.Xr strcmp 3 .
59.Pp
60.Fn tfind
61searches for the datum matched by the argument
62.Fa key
63in the binary tree rooted at
64.Fa rootp ,
65returning a pointer to the datum if it is found and
66.Dv NULL
67if it is not.
68.Pp
69.Fn tsearch
70is identical to
71.Fn tfind
72except that if no match is found,
73.Fa key
74is inserted into the tree and a pointer to it is returned.
75If
76.Fa rootp
77points to a null value a new binary search tree is created.
78.Pp
79.Fn tdelete
80deletes a node from the specified binary search tree and returns
81a pointer to the parent of the node to be deleted.
82It takes the same arguments as
83.Fn tfind
84and
85.Fn tsearch .
86If the node to be deleted is the root of the binary search tree,
87.Fa rootp
88will be adjusted.
89.Pp
90.Fn twalk
91walks the binary search tree rooted in
92.Fa root
93and calls the function
94.Fa action
95on each node.
96.Fa action
97is called with three arguments: a pointer to the current node,
98a value from the enum
99.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
100specifying the traversal type, and a node level (where level
101zero is the root of the tree).
102.Sh SEE ALSO
103.Xr bsearch 3 ,
104.Xr lsearch 3
105.Sh RETURN VALUES
106The
107.Fn tsearch
108function returns
109.Dv NULL
110if allocation of a new node fails (usually
111due to a lack of free memory).
112.Pp
113.Fn tfind ,
114.Fn tsearch ,
115and
116.Fn tdelete
117return
118.Dv NULL
119if
120.Fa rootp
121is
122.Dv NULL
123or the datum cannot be found.
124.Pp
125The
126.Fn twalk
127function returns no value.
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..0ad5866172
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,126 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12
13#include <search.h>
14#include <stdlib.h>
15
16typedef struct node_t {
17 char *key;
18 struct node_t *left, *right;
19} node;
20
21/* find or insert datum into search tree */
22void *
23tsearch(vkey, vrootp, compar)
24 const void *vkey; /* key to be located */
25 void **vrootp; /* address of tree root */
26 int (*compar)(const void *, const void *);
27{
28 register node *q;
29 char *key = (char *)vkey;
30 node **rootp = (node **)vrootp;
31
32 if (rootp == (struct node_t **)0)
33 return ((void *)0);
34 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
35 int r;
36
37 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
38 return ((void *)*rootp); /* we found it! */
39 rootp = (r < 0) ?
40 &(*rootp)->left : /* T3: follow left branch */
41 &(*rootp)->right; /* T4: follow right branch */
42 }
43 q = (node *) malloc(sizeof(node)); /* T5: key not found */
44 if (q != (struct node_t *)0) { /* make new node */
45 *rootp = q; /* link new node to old */
46 q->key = key; /* initialize new node */
47 q->left = q->right = (struct node_t *)0;
48 }
49 return ((void *)q);
50}
51
52/* delete node with given key */
53void *
54tdelete(vkey, vrootp, compar)
55 const void *vkey; /* key to be deleted */
56 void **vrootp; /* address of the root of tree */
57 int (*compar)(const void *, const void *);
58{
59 node **rootp = (node **)vrootp;
60 char *key = (char *)vkey;
61 node *p;
62 register node *q;
63 register node *r;
64 int cmp;
65
66 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
67 return ((struct node_t *)0);
68 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
69 p = *rootp;
70 rootp = (cmp < 0) ?
71 &(*rootp)->left : /* follow left branch */
72 &(*rootp)->right; /* follow right branch */
73 if (*rootp == (struct node_t *)0)
74 return ((void *)0); /* key not found */
75 }
76 r = (*rootp)->right; /* D1: */
77 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
78 q = r;
79 else if (r != (struct node_t *)0) { /* Right link is null? */
80 if (r->left == (struct node_t *)0) { /* D2: Find successor */
81 r->left = q;
82 q = r;
83 } else { /* D3: Find (struct node_t *)0 link */
84 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
85 r = q;
86 r->left = q->right;
87 q->left = (*rootp)->left;
88 q->right = (*rootp)->right;
89 }
90 }
91 free((struct node_t *) *rootp); /* D4: Free node */
92 *rootp = q; /* link parent to new node */
93 return(p);
94}
95
96/* Walk the nodes of a tree */
97static void
98trecurse(root, action, level)
99 register node *root; /* Root of the tree to be walked */
100 register void (*action)(); /* Function to be called at each node */
101 register int level;
102{
103 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
104 (*action)(root, leaf, level);
105 else {
106 (*action)(root, preorder, level);
107 if (root->left != (struct node_t *)0)
108 trecurse(root->left, action, level + 1);
109 (*action)(root, postorder, level);
110 if (root->right != (struct node_t *)0)
111 trecurse(root->right, action, level + 1);
112 (*action)(root, endorder, level);
113 }
114}
115
116/* Walk the nodes of a tree */
117void
118twalk(vroot, action)
119 const void *vroot; /* Root of the tree to be walked */
120 void (*action)(const void *, VISIT, int);
121{
122 node *root = (node *)vroot;
123
124 if (root != (node *)0 && action != (void(*)())0)
125 trecurse(root, action, 0);
126}