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.inc41
-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.c88
-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.310
-rw-r--r--src/lib/libc/stdlib/atol.c3
-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.371
-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/erand48.c4
-rw-r--r--src/lib/libc/stdlib/exit.324
-rw-r--r--src/lib/libc/stdlib/exit.c32
-rw-r--r--src/lib/libc/stdlib/free.382
-rw-r--r--src/lib/libc/stdlib/getenv.366
-rw-r--r--src/lib/libc/stdlib/getenv.c65
-rw-r--r--src/lib/libc/stdlib/getopt.3128
-rw-r--r--src/lib/libc/stdlib/getopt.c3
-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/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/malloc.3376
-rw-r--r--src/lib/libc/stdlib/malloc.c1592
-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.355
-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.335
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3105
-rw-r--r--src/lib/libc/stdlib/random.c95
-rw-r--r--src/lib/libc/stdlib/realloc.3100
-rw-r--r--src/lib/libc/stdlib/realpath.320
-rw-r--r--src/lib/libc/stdlib/realpath.c23
-rw-r--r--src/lib/libc/stdlib/seed48.c4
-rw-r--r--src/lib/libc/stdlib/setenv.c13
-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.c251
-rw-r--r--src/lib/libc/stdlib/strtol.3132
-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.3129
-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
86 files changed, 3704 insertions, 1568 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 782a4ab022..4b4c88b9af 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 bsearch.c calloc.c \
8 exit.c getenv.c getopt.c heapsort.c l64a.c malloc.c merge.c \ 7 cfree.c exit.c getenv.c getopt.c getsubopt.c heapsort.c l64a.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 8 malloc.c merge.c multibyte.c putenv.c qsort.c radixsort.c rand.c \
10 setenv.c strtod.c strtol.c strtoq.c strtoul.c strtouq.c system.c \ 9 random.c realpath.c setenv.c strtod.c strtol.c strtoll.c strtoul.c \
10 strtoull.c system.c tfind.c tsearch.c \
11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \ 11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \
12 mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c 12 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,25 @@ 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 \ 35MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 36 div.3 exit.3 getenv.3 getopt.3 getsubopt.3 labs.3 ldiv.3 \
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 37 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 \
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 38 random.3 realpath.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
35 system.3
36 39
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 40MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
41MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
42MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 43MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 44MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 45MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 46MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 47MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 48MLINKS+=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 49MLINKS+=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 50MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
51MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
52MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
53MLINKS+=tsearch.3 tfind.3
54MLINKS+=tsearch.3 tdelete.3
55MLINKS+=tsearch.3 twalk.3
56MLINKS+=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..787634303c
--- /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.5 2000/04/20 13:50:01 aaron 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..41a9f0f48b 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.7 2001/08/12 12:03:01 heko 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
43void (*__cleanup)();
42 44
43void 45void
44abort() 46abort()
45{ 47{
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);
58#ifdef _THREAD_SAFE
59 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
60#else /* _THREAD_SAFE */
54 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 61 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
62#endif /* _THREAD_SAFE */
63
64 /*
65 * POSIX requires we flush stdio buffers on abort
66 */
67 if (cleanup_called == 0 && __cleanup != NULL) {
68 cleanup_called = 1;
69 (*__cleanup)();
70 }
71
55 (void)kill(getpid(), SIGABRT); 72 (void)kill(getpid(), SIGABRT);
56 73
57 /* 74 /*
@@ -59,7 +76,11 @@ 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);
79#ifdef _THREAD_SAFE
80 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
81#else /* _THREAD_SAFE */
62 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 82 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
83#endif /* _THREAD_SAFE */
63 (void)kill(getpid(), SIGABRT); 84 (void)kill(getpid(), SIGABRT);
64 exit(1); 85 exit(1);
65} 86}
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..da5a0ddda0 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,47 +1,44 @@
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.6 2002/09/06 22:48:34 henning 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/*
@@ -51,18 +48,37 @@ int
51atexit(fn) 48atexit(fn)
52 void (*fn)(); 49 void (*fn)();
53{ 50{
54 static struct atexit __atexit0; /* one guaranteed table */ 51 register struct atexit *p = __atexit;
55 register struct atexit *p; 52 register int pgsize = getpagesize();
56 53
57 if ((p = __atexit) == NULL) 54 if (pgsize < sizeof(*p))
58 __atexit = p = &__atexit0; 55 return (-1);
59 else if (p->ind >= ATEXIT_SIZE) { 56 if (p != NULL) {
60 if ((p = malloc(sizeof(*p))) == NULL) 57 if (p->ind + 1 >= p->max)
58 p = NULL;
59 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
60 return (-1);
61 }
62 if (p == NULL) {
63 if (__atexit_invalid) {
64 /* malloc.c wants the first mmap() for sbrk()
65 games ('nice hack'), so enforce
66 malloc_init() with a dummy call. */
67 free(malloc(1));
68 __atexit_invalid = 0;
69 }
70 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
71 MAP_ANON | MAP_PRIVATE, -1, 0);
72 if (p == MAP_FAILED)
61 return (-1); 73 return (-1);
62 p->ind = 0; 74 p->ind = 0;
75 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
76 sizeof(p->fns[0]);
63 p->next = __atexit; 77 p->next = __atexit;
64 __atexit = p; 78 __atexit = p;
65 } 79 }
66 p->fns[p->ind++] = fn; 80 p->fns[p->ind++] = fn;
81 if (mprotect(p, pgsize, PROT_READ))
82 return (-1);
67 return (0); 83 return (0);
68} 84}
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..53a518997f 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.4 2000/04/20 13:50:01 aaron 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:
@@ -70,6 +69,5 @@ strtol(nptr, (char **)NULL, 10);
70.Sh STANDARDS 69.Sh STANDARDS
71The 70The
72.Fn atol 71.Fn atol
73function 72function conforms to
74conforms to
75.St -ansiC . 73.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/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.3 b/src/lib/libc/stdlib/calloc.3
deleted file mode 100644
index d0754b46a0..0000000000
--- a/src/lib/libc/stdlib/calloc.3
+++ /dev/null
@@ -1,71 +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: @(#)calloc.3 5.2 (Berkeley) 6/29/91
37.\" $Id: calloc.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\"
39.Dd June 29, 1991
40.Dt CALLOC 3
41.Os
42.Sh NAME
43.Nm calloc
44.Nd allocate clean memory (zero initialized space)
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void *
48.Fn calloc "size_t nmemb" "size_t size"
49.Sh DESCRIPTION
50The
51.Fn calloc
52function allocates space for an array of
53.Fa nmemb
54objects, each of whose size is
55.Fa size .
56The space is initialized to all bits zero.
57.Sh RETURN VALUES
58The
59.Fn calloc
60function returns
61a pointer to the
62the allocated space if successful; otherwise a null pointer is returned.
63.Sh SEE ALSO
64.Xr malloc 3 ,
65.Xr realloc 3 ,
66.Xr free 3
67.Sh STANDARDS
68The
69.Fn calloc
70function conforms to
71.St -ansiC .
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/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..bcfdfd38f5 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.6 2001/07/27 23:48:12 mpech 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,27 @@ Unlink all files created with the
66.Xr tmpfile 3 66.Xr tmpfile 3
67function. 67function.
68.El 68.El
69Following this,
70.Fn exit
71calls
72.Xr _exit 2 .
73Note that typically
74.Xr exit 2
75only passes the lower 8 bits of
76.Fa status
77on to the parent, thus negative values have less meaning.
69.Sh RETURN VALUES 78.Sh RETURN VALUES
70The 79The
71.Fn exit 80.Fn exit
72function 81function never returns.
73never returns.
74.Sh SEE ALSO 82.Sh SEE ALSO
75.Xr _exit 2 , 83.Xr _exit 2 ,
76.Xr atexit 3 , 84.Xr atexit 3 ,
77.Xr intro 3 , 85.Xr intro 3 ,
86.Xr sysexits 3 ,
78.Xr tmpfile 3 87.Xr tmpfile 3
79.Sh STANDARDS 88.Sh STANDARDS
80The 89The
81.Fn exit 90.Fn exit
82function 91function conforms to
83conforms to
84.St -ansiC . 92.St -ansiC .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index b1412f42bb..c69639125e 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -32,29 +32,47 @@
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.7 2002/08/30 07:58:07 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)(); 45void (*__cleanup)();
44 46
45/* 47/*
48 * This variable is zero until a process has created a thread.
49 * It is used to avoid calling locking functions in libc when they
50 * are not required. By default, libc is intended to be(come)
51 * thread-safe, but without a (significant) penalty to non-threaded
52 * processes.
53 */
54int __isthreaded = 0;
55
56/*
46 * Exit, flushing stdio buffers if necessary. 57 * Exit, flushing stdio buffers if necessary.
47 */ 58 */
48void 59void
49exit(status) 60exit(status)
50 int status; 61 int status;
51{ 62{
52 register struct atexit *p; 63 register struct atexit *p, *q;
53 register int n; 64 register int n, pgsize = getpagesize();
54 65
55 for (p = __atexit; p; p = p->next) 66 if (!__atexit_invalid) {
56 for (n = p->ind; --n >= 0;) 67 p = __atexit;
57 (*p->fns[n])(); 68 while (p != NULL) {
69 for (n = p->ind; --n >= 0;)
70 (*p->fns[n])();
71 q = p;
72 p = p->next;
73 munmap(q, pgsize);
74 }
75 }
58 if (__cleanup) 76 if (__cleanup)
59 (*__cleanup)(); 77 (*__cleanup)();
60 _exit(status); 78 _exit(status);
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/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..4db86df915 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,28 +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.4 1998/07/16 18:02:33 deraadt 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/* 41/*
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
56/*
57 * __findenv -- 42 * __findenv --
58 * Returns pointer to value associated with name, if any, else NULL. 43 * Returns pointer to value associated with name, if any, else NULL.
59 * Sets offset to be the offset of the name/value combination in the 44 * Sets offset to be the offset of the name/value combination in the
@@ -64,19 +49,41 @@ getenv(name)
64 */ 49 */
65char * 50char *
66__findenv(name, offset) 51__findenv(name, offset)
67 register char *name; 52 register const char *name;
68 int *offset; 53 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;
73 59
74 for (C = name, len = 0; *C && *C != '='; ++C, ++len); 60 if (name == NULL || environ == NULL)
75 for (P = environ; *P; ++P) 61 return (NULL);
76 if (!strncmp(*P, name, len)) 62 for (np = name; *np && *np != '='; ++np)
77 if (*(C = *P + len) == '=') { 63 ;
78 *offset = P - environ; 64 len = np - name;
79 return(++C); 65 for (p = environ; (cp = *p) != NULL; ++p) {
80 } 66 for (np = name, i = len; i && *cp; i--)
81 return(NULL); 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;
86 char *__findenv();
87
88 return(__findenv(name, &offset));
82} 89}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
index f843881afd..4acbe69606 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.17 2002/08/19 22:29:52 miod Exp $
33.\" 33.\"
34.Dd April 19, 1994 34.Dd April 19, 1994
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,31 +126,58 @@ 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.
129.Sh EXAMPLES
130.Bd -literal -compact
131int bflag, ch, fd;
132
133bflag = 0;
134while ((ch = getopt(argc, argv, "bf:")) != -1) {
135 switch (ch) {
136 case 'b':
137 bflag = 1;
138 break;
139 case 'f':
140 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
141 (void)fprintf(stderr,
142 "myname: %s: %s\en", optarg, strerror(errno));
143 exit(1);
144 }
145 break;
146 case '?':
147 default:
148 usage();
149 }
150}
151argc -= optind;
152argv += optind;
153.Ed
154.Sh SEE ALSO
155.Xr getopt 1 ,
156.Xr getsubopt 3
136.Sh DIAGNOSTICS 157.Sh DIAGNOSTICS
137If the 158If the
138.Fn getopt 159.Fn getopt
139function encounters a character not found in the string 160function encounters a character not found in the string
140.Va optarg 161.Va optstring
141or detects 162or detects
142a missing option argument it writes an error message and returns 163a missing option argument it writes an error message to
143.Ql ? 164.Em stderr
144to the 165and returns
145.Em stderr . 166.Ql ? .
146Setting 167Setting
147.Va opterr 168.Va opterr
148to a zero will disable these error messages. 169to a zero will disable these error messages.
149If 170If
150.Va optstring 171.Va optstring
151has a leading 172has a leading
152.Ql \&: 173.Ql \&:
153then a missing option argument causes a 174then a missing option argument causes a
154.Ql \&: 175.Ql \&:
155to be returned in addition to suppressing any error messages. 176to be returned in addition to suppressing any error messages.
156.Pp 177.Pp
157Option arguments are allowed to begin with 178Option arguments are allowed to begin with
158.Dq Li \- ; 179.Ql - ;
159this is reasonable but 180this is reasonable but reduces the amount of error checking possible.
160reduces the amount of error checking possible.
161.Sh EXTENSIONS 181.Sh EXTENSIONS
162The 182The
163.Va optreset 183.Va optreset
@@ -167,53 +187,27 @@ function multiple times.
167This is an extension to the 187This is an extension to the
168.St -p1003.2 188.St -p1003.2
169specification. 189specification.
170.Sh EXAMPLE
171.Bd -literal -compact
172extern char *optarg;
173extern int optind;
174int bflag, ch, fd;
175
176bflag = 0;
177while ((ch = getopt(argc, argv, "bf:")) != -1)
178 switch(ch) {
179 case 'b':
180 bflag = 1;
181 break;
182 case 'f':
183 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
184 (void)fprintf(stderr,
185 "myname: %s: %s\en", optarg, strerror(errno));
186 exit(1);
187 }
188 break;
189 case '?':
190 default:
191 usage();
192}
193argc -= optind;
194argv += optind;
195.Ed
196.Sh HISTORY 190.Sh HISTORY
197The 191The
198.Fn getopt 192.Fn getopt
199function appeared 193function appeared in
200.Bx 4.3 . 194.Bx 4.3 .
201.Sh BUGS 195.Sh BUGS
202The 196The
203.Fn getopt 197.Fn getopt
204function was once specified to return 198function was once specified to return
205.Dv EOF 199.Dv EOF
206instead of \-1. 200instead of \-1.
207This was changed by 201This was changed by
208.St -p1003.2-92 202.St -p1003.2-92
209to decouple 203to decouple
210.Fn getopt 204.Fn getopt
211from 205from
212.Pa <stdio.h> . 206.Pa <stdio.h> .
213.Pp 207.Pp
214A single dash 208A single dash
215.Dq Li - 209.Pq Ql -
216may be specified as an character in 210may be specified as a character in
217.Fa optstring , 211.Fa optstring ,
218however it should 212however it should
219.Em never 213.Em never
@@ -221,7 +215,7 @@ have an argument associated with it.
221This allows 215This allows
222.Fn getopt 216.Fn getopt
223to be used with programs that expect 217to be used with programs that expect
224.Dq Li - 218.Ql -
225as an option flag. 219as an option flag.
226This practice is wrong, and should not be used in any current development. 220This practice is wrong, and should not be used in any current development.
227It is provided for backward compatibility 221It is provided for backward compatibility
@@ -242,18 +236,18 @@ It is provided for backward compatibility
242.Em only . 236.Em only .
243The following code fragment works in most cases. 237The following code fragment works in most cases.
244.Bd -literal -offset indent 238.Bd -literal -offset indent
245int length; 239long length;
246char *p; 240char *p;
247 241
248while ((c = getopt(argc, argv, "0123456789")) != -1) 242while ((c = getopt(argc, argv, "0123456789")) != -1) {
249 switch (c) { 243 switch (c) {
250 case '0': case '1': case '2': case '3': case '4': 244 case '0': case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9': 245 case '5': case '6': case '7': case '8': case '9':
252 p = argv[optind - 1]; 246 p = argv[optind - 1];
253 if (p[0] == '-' && p[1] == ch && !p[2]) 247 if (p[0] == '-' && p[1] == ch && !p[2])
254 length = atoi(++p); 248 length = ch - '0';
255 else 249 else
256 length = atoi(argv[optind] + 1); 250 length = strtol(argv[optind] + 1, NULL, 10);
257 break; 251 break;
258 } 252 }
259} 253}
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
index 63c5e6a479..b7f6163662 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.2 1996/08/19 08:33:32 tholo 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>
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..8a17da4ea5
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,147 @@
1.\" $OpenBSD: getsubopt.3,v 1.5 2000/12/15 14:31:17 aaron 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/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/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 3bbf2bf65e..8f05c38e86 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.24 2001/12/05 09:49:39 deraadt 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
259is 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..4e90ce402e 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1305 @@
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.48 2002/05/27 03:13:23 deraadt 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 <errno.h>
50
51/*
52 * The basic parameters you can tweak.
53 *
54 * malloc_pageshift pagesize = 1 << malloc_pageshift
55 * It's probably best if this is the native
56 * page size, but it shouldn't have to be.
57 *
58 * malloc_minsize minimum size of an allocation in bytes.
59 * If this is too small it's too much work
60 * to manage them. This is also the smallest
61 * unit of alignment used for the storage
62 * returned by malloc/realloc.
63 *
64 */
65
66#if defined(__OpenBSD__) && defined(__sparc__)
67# define malloc_pageshift 13U
68#endif /* __OpenBSD__ */
69
70#ifdef _THREAD_SAFE
71# include "thread_private.h"
72# if 0
73 /* kernel threads */
74# include <pthread.h>
75 static pthread_mutex_t malloc_lock;
76# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
77# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
78# define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0);
79# else
80 /* user threads */
81# include "spinlock.h"
82 static spinlock_t malloc_lock = _SPINLOCK_INITIALIZER;
83# define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&malloc_lock)
84# define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&malloc_lock)
85# define THREAD_LOCK_INIT()
86 /*
87 * Malloc can't use the wrapped write() if it fails very early, so
88 * we use the unwrapped syscall _thread_sys_write()
89 */
90# define write _thread_sys_write
91 ssize_t write(int, const void *, size_t);
92# undef malloc
93# undef realloc
94# undef free
95# endif
96#else
97 /* no threads */
98# define THREAD_LOCK()
99# define THREAD_UNLOCK()
100# define THREAD_LOCK_INIT()
101#endif
54 102
55#define NULL 0 103/*
104 * No user serviceable parts behind this point.
105 *
106 * This structure describes a page worth of chunks.
107 */
56 108
57static void morecore(); 109struct pginfo {
58static int findbucket(); 110 struct pginfo *next; /* next on the free list */
111 void *page; /* Pointer to the page */
112 u_short size; /* size of this page's chunks */
113 u_short shift; /* How far to shift for this size chunks */
114 u_short free; /* How many free chunks */
115 u_short total; /* How many chunk */
116 u_long bits[1]; /* Which chunks are free */
117};
59 118
60/* 119/*
61 * The overhead on a block is at least 4 bytes. When free, this space 120 * This structure describes a number of free pages.
62 * contains a pointer to the next free block, and the bottom two bits must
63 * be zero. When in use, the first byte is set to MAGIC, and the second
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 */ 121 */
70union overhead { 122
71 union overhead *ov_next; /* when free */ 123struct pgfree {
72 struct { 124 struct pgfree *next; /* next run of free pages */
73 u_char ovu_magic; /* magic number */ 125 struct pgfree *prev; /* prev run of free pages */
74 u_char ovu_index; /* bucket # */ 126 void *page; /* pointer to free pages */
75#ifdef RCHECK 127 void *end; /* pointer to end of free pages */
76 u_short ovu_rmagic; /* range magic number */ 128 u_long size; /* number of bytes free */
77 u_long ovu_size; /* actual block size */
78#endif
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}; 129};
85 130
86#define MAGIC 0xef /* magic # on accounting info */ 131/*
87#define RMAGIC 0x5555 /* magic # on range info */ 132 * How many bits per u_long in the bitmap.
133 * Change only if not 8 bits/byte
134 */
135#define MALLOC_BITS (8*sizeof(u_long))
136
137/*
138 * Magic values to put in the page_directory
139 */
140#define MALLOC_NOT_MINE ((struct pginfo*) 0)
141#define MALLOC_FREE ((struct pginfo*) 1)
142#define MALLOC_FIRST ((struct pginfo*) 2)
143#define MALLOC_FOLLOW ((struct pginfo*) 3)
144#define MALLOC_MAGIC ((struct pginfo*) 4)
145
146#ifndef malloc_pageshift
147#define malloc_pageshift (PGSHIFT)
148#endif
149
150#ifndef malloc_minsize
151#define malloc_minsize 16U
152#endif
153
154#ifndef malloc_pageshift
155#error "malloc_pageshift undefined"
156#endif
157
158#if !defined(malloc_pagesize)
159#define malloc_pagesize (1UL<<malloc_pageshift)
160#endif
161
162#if ((1UL<<malloc_pageshift) != malloc_pagesize)
163#error "(1UL<<malloc_pageshift) != malloc_pagesize"
164#endif
165
166#ifndef malloc_maxsize
167#define malloc_maxsize ((malloc_pagesize)>>1)
168#endif
88 169
89#ifdef RCHECK 170/* A mask for the offset inside a page. */
90#define RSLOP sizeof (u_short) 171#define malloc_pagemask ((malloc_pagesize)-1)
172
173#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
174#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
175
176/* fd of /dev/zero */
177#ifdef USE_DEV_ZERO
178static int fdzero;
179#define MMAP_FD fdzero
180#define INIT_MMAP() \
181 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
182 wrterror("open of /dev/zero"); }
91#else 183#else
92#define RSLOP 0 184#define MMAP_FD (-1)
185#define INIT_MMAP()
186#endif
187
188/* Set when initialization has been done */
189static unsigned int malloc_started;
190
191/* Number of free pages we cache */
192static unsigned int malloc_cache = 16;
193
194/* The offset from pagenumber to index into the page directory */
195static u_long malloc_origo;
196
197/* The last index in the page directory we care about */
198static u_long last_index;
199
200/* Pointer to page directory. Allocated "as if with" malloc */
201static struct pginfo **page_dir;
202
203/* How many slots in the page directory */
204static size_t malloc_ninfo;
205
206/* Free pages line up here */
207static struct pgfree free_list;
208
209/* Abort(), user doesn't handle problems. */
210static int malloc_abort;
211
212/* Are we trying to die ? */
213static int suicide;
214
215#ifdef MALLOC_STATS
216/* dump statistics */
217static int malloc_stats;
218#endif
219
220/* avoid outputting warnings? */
221static int malloc_silent;
222
223/* always realloc ? */
224static int malloc_realloc;
225
226#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
227/* pass the kernel a hint on free pages ? */
228static int malloc_hint;
229#endif
230
231/* xmalloc behaviour ? */
232static int malloc_xmalloc;
233
234/* zero fill ? */
235static int malloc_zero;
236
237/* junk fill ? */
238static int malloc_junk;
239
240#ifdef __FreeBSD__
241/* utrace ? */
242static int malloc_utrace;
243
244struct ut { void *p; size_t s; void *r; };
245
246void utrace(struct ut *, int);
247
248#define UTRACE(a, b, c) \
249 if (malloc_utrace) \
250 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
251#else /* !__FreeBSD__ */
252#define UTRACE(a,b,c)
93#endif 253#endif
94 254
255/* my last break. */
256static void *malloc_brk;
257
258/* one location cache for free-list holders */
259static struct pgfree *px;
260
261/* compile-time options */
262char *malloc_options;
263
264/* Name of the current public function */
265static char *malloc_func;
266
267/* Macro for mmap */
268#define MMAP(size) \
269 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
270 MMAP_FD, (off_t)0);
271
95/* 272/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 273 * Necessary function declarations
97 * smallest allocatable block is 8 bytes. The overhead information
98 * precedes the data area returned to the user.
99 */ 274 */
100#define NBUCKETS 30 275static int extend_pgdir(u_long index);
101static union overhead *nextf[NBUCKETS]; 276static void *imalloc(size_t size);
102extern char *sbrk(); 277static void ifree(void *ptr);
278static void *irealloc(void *ptr, size_t size);
279static void *malloc_bytes(size_t size);
280
281#ifdef MALLOC_STATS
282void
283malloc_dump(fd)
284 FILE *fd;
285{
286 struct pginfo **pd;
287 struct pgfree *pf;
288 int j;
289
290 pd = page_dir;
291
292 /* print out all the pages */
293 for(j=0;j<=last_index;j++) {
294 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
295 if (pd[j] == MALLOC_NOT_MINE) {
296 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
297 ;
298 j--;
299 fprintf(fd, ".. %5d not mine\n", j);
300 } else if (pd[j] == MALLOC_FREE) {
301 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
302 ;
303 j--;
304 fprintf(fd, ".. %5d free\n", j);
305 } else if (pd[j] == MALLOC_FIRST) {
306 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
307 ;
308 j--;
309 fprintf(fd, ".. %5d in use\n", j);
310 } else if (pd[j] < MALLOC_MAGIC) {
311 fprintf(fd, "(%p)\n", pd[j]);
312 } else {
313 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
314 pd[j], pd[j]->free, pd[j]->total,
315 pd[j]->size, pd[j]->page, pd[j]->next);
316 }
317 }
318
319 for(pf=free_list.next; pf; pf=pf->next) {
320 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
321 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
322 if (pf == pf->next) {
323 fprintf(fd, "Free_list loops.\n");
324 break;
325 }
326 }
327
328 /* print out various info */
329 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
330 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
331 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
332 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
333 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
334 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
335 (last_index + malloc_pageshift) << malloc_pageshift);
336 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
337}
338#endif /* MALLOC_STATS */
339
340extern char *__progname;
341
342static void
343wrterror(p)
344 char *p;
345{
346 char *q = " error: ";
347 struct iovec iov[4];
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 suicide = 1;
360#ifdef MALLOC_STATS
361 if (malloc_stats)
362 malloc_dump(stderr);
363#endif /* MALLOC_STATS */
364 abort();
365}
366
367static void
368wrtwarning(p)
369 char *p;
370{
371 char *q = " warning: ";
372 struct iovec iov[4];
373
374 if (malloc_abort)
375 wrterror(p);
376 else if (malloc_silent)
377 return;
378
379 iov[0].iov_base = __progname;
380 iov[0].iov_len = strlen(__progname);
381 iov[1].iov_base = malloc_func;
382 iov[1].iov_len = strlen(malloc_func);
383 iov[2].iov_base = q;
384 iov[2].iov_len = strlen(q);
385 iov[3].iov_base = p;
386 iov[3].iov_len = strlen(p);
387 writev(STDERR_FILENO, iov, 4);
388}
389
390#ifdef MALLOC_STATS
391static void
392malloc_exit()
393{
394 FILE *fd = fopen("malloc.out", "a");
395 char *q = "malloc() warning: Couldn't dump stats.\n";
396 if (fd) {
397 malloc_dump(fd);
398 fclose(fd);
399 } else
400 write(2, q, strlen(q));
401}
402#endif /* MALLOC_STATS */
103 403
104static int pagesz; /* page size */
105static int pagebucket; /* page size bucket */
106 404
107#ifdef MSTATS
108/* 405/*
109 * nmalloc[i] is the difference between the number of mallocs and frees 406 * Allocate a number of pages from the OS
110 * for a given block size.
111 */ 407 */
112static u_int nmalloc[NBUCKETS]; 408static void *
113#include <stdio.h> 409map_pages(pages)
114#endif 410 int pages;
411{
412 caddr_t result, tail;
115 413
116#if defined(DEBUG) || defined(RCHECK) 414 result = (caddr_t)pageround((u_long)sbrk(0));
117#define ASSERT(p) if (!(p)) botch("p") 415 tail = result + (pages << malloc_pageshift);
118#include <stdio.h> 416
119static 417 if (brk(tail)) {
120botch(s) 418#ifdef MALLOC_EXTRA_SANITY
121 char *s; 419 wrterror("(ES): map_pages fails\n");
420#endif /* MALLOC_EXTRA_SANITY */
421 return 0;
422 }
423
424 last_index = ptr2index(tail) - 1;
425 malloc_brk = tail;
426
427 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
428 return 0;
429
430 return result;
431}
432
433/*
434 * Extend page directory
435 */
436static int
437extend_pgdir(index)
438 u_long index;
122{ 439{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 440 struct pginfo **new, **old;
124 (void) fflush(stderr); /* just in case user buffered it */ 441 size_t i, oldlen;
125 abort(); 442
443 /* Make it this many pages */
444 i = index * sizeof *page_dir;
445 i /= malloc_pagesize;
446 i += 2;
447
448 /* remember the old mapping size */
449 oldlen = malloc_ninfo * sizeof *page_dir;
450
451 /*
452 * NOTE: we allocate new pages and copy the directory rather than tempt
453 * fate by trying to "grow" the region.. There is nothing to prevent
454 * us from accidently re-mapping space that's been allocated by our caller
455 * via dlopen() or other mmap().
456 *
457 * The copy problem is not too bad, as there is 4K of page index per
458 * 4MB of malloc arena.
459 *
460 * We can totally avoid the copy if we open a file descriptor to associate
461 * the anon mappings with. Then, when we remap the pages at the new
462 * address, the old pages will be "magically" remapped.. But this means
463 * keeping open a "secret" file descriptor.....
464 */
465
466 /* Get new pages */
467 new = (struct pginfo**) MMAP(i * malloc_pagesize);
468 if (new == MAP_FAILED)
469 return 0;
470
471 /* Copy the old stuff */
472 memcpy(new, page_dir,
473 malloc_ninfo * sizeof *page_dir);
474
475 /* register the new size */
476 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
477
478 /* swap the pointers */
479 old = page_dir;
480 page_dir = new;
481
482 /* Now free the old stuff */
483 munmap(old, oldlen);
484 return 1;
126} 485}
127#else
128#define ASSERT(p)
129#endif
130 486
131void * 487/*
132malloc(nbytes) 488 * Initialize the world
133 size_t nbytes; 489 */
490static void
491malloc_init ()
134{ 492{
135 register union overhead *op; 493 char *p, b[64];
136 register long bucket, n; 494 int i, j;
137 register unsigned amt; 495 int save_errno = errno;
138 496
139 /* 497 THREAD_LOCK_INIT();
140 * First time malloc is called, setup page size and 498
141 * align break pointer so all data will be page aligned. 499 INIT_MMAP();
142 */ 500
143 if (pagesz == 0) { 501#ifdef MALLOC_EXTRA_SANITY
144 pagesz = n = getpagesize(); 502 malloc_junk = 1;
145 op = (union overhead *)sbrk(0); 503#endif /* MALLOC_EXTRA_SANITY */
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 504
147 if (n < 0) 505 for (i = 0; i < 3; i++) {
148 n += pagesz; 506 if (i == 0) {
149 if (n) { 507 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
150 if (sbrk(n) == (char *)-1) 508 if (j <= 0)
151 return (NULL); 509 continue;
152 } 510 b[j] = '\0';
153 bucket = 0; 511 p = b;
154 amt = 8; 512 } else if (i == 1) {
155 while (pagesz > amt) { 513 if (issetugid() == 0)
156 amt <<= 1; 514 p = getenv("MALLOC_OPTIONS");
157 bucket++; 515 else
158 } 516 continue;
159 pagebucket = bucket; 517 } else if (i == 2) {
160 } 518 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 } 519 }
179 while (nbytes > amt + n) { 520 for (; p && *p; p++) {
180 amt <<= 1; 521 switch (*p) {
181 if (amt == 0) 522 case '>': malloc_cache <<= 1; break;
182 return (NULL); 523 case '<': malloc_cache >>= 1; break;
183 bucket++; 524 case 'a': malloc_abort = 0; break;
525 case 'A': malloc_abort = 1; break;
526#ifdef MALLOC_STATS
527 case 'd': malloc_stats = 0; break;
528 case 'D': malloc_stats = 1; break;
529#endif /* MALLOC_STATS */
530#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
531 case 'h': malloc_hint = 0; break;
532 case 'H': malloc_hint = 1; break;
533#endif /* __FreeBSD__ */
534 case 'r': malloc_realloc = 0; break;
535 case 'R': malloc_realloc = 1; break;
536 case 'j': malloc_junk = 0; break;
537 case 'J': malloc_junk = 1; break;
538 case 'n': malloc_silent = 0; break;
539 case 'N': malloc_silent = 1; break;
540#ifdef __FreeBSD__
541 case 'u': malloc_utrace = 0; break;
542 case 'U': malloc_utrace = 1; break;
543#endif /* __FreeBSD__ */
544 case 'x': malloc_xmalloc = 0; break;
545 case 'X': malloc_xmalloc = 1; break;
546 case 'z': malloc_zero = 0; break;
547 case 'Z': malloc_zero = 1; break;
548 default:
549 j = malloc_abort;
550 malloc_abort = 0;
551 wrtwarning("unknown char in MALLOC_OPTIONS\n");
552 malloc_abort = j;
553 break;
554 }
184 } 555 }
185 /* 556 }
186 * If nothing in hash bucket right now, 557
187 * request more memory from the system. 558 UTRACE(0, 0, 0);
188 */ 559
189 if ((op = nextf[bucket]) == NULL) { 560 /*
190 morecore(bucket); 561 * We want junk in the entire allocation, and zero only in the part
191 if ((op = nextf[bucket]) == NULL) 562 * the user asked for.
192 return (NULL); 563 */
564 if (malloc_zero)
565 malloc_junk=1;
566
567#ifdef MALLOC_STATS
568 if (malloc_stats)
569 atexit(malloc_exit);
570#endif /* MALLOC_STATS */
571
572 /* Allocate one page for the page directory */
573 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
574
575 if (page_dir == MAP_FAILED)
576 wrterror("mmap(2) failed, check limits.\n");
577
578 /*
579 * We need a maximum of malloc_pageshift buckets, steal these from the
580 * front of the page_directory;
581 */
582 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
583 malloc_origo -= malloc_pageshift;
584
585 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
586
587 /* Been here, done that */
588 malloc_started++;
589
590 /* Recalculate the cache size in bytes, and make sure it's nonzero */
591
592 if (!malloc_cache)
593 malloc_cache++;
594
595 malloc_cache <<= malloc_pageshift;
596
597 /*
598 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
599 * We can sbrk(2) further back when we keep this on a low address.
600 */
601 px = (struct pgfree *) imalloc (sizeof *px);
602 errno = save_errno;
603}
604
605/*
606 * Allocate a number of complete pages
607 */
608static void *
609malloc_pages(size)
610 size_t size;
611{
612 void *p, *delay_free = 0;
613 int i;
614 struct pgfree *pf;
615 u_long index;
616
617 size = pageround(size);
618
619 p = 0;
620 /* Look for free pages before asking for more */
621 for(pf = free_list.next; pf; pf = pf->next) {
622
623#ifdef MALLOC_EXTRA_SANITY
624 if (pf->size & malloc_pagemask)
625 wrterror("(ES): junk length entry on free_list\n");
626 if (!pf->size)
627 wrterror("(ES): zero length entry on free_list\n");
628 if (pf->page == pf->end)
629 wrterror("(ES): zero entry on free_list\n");
630 if (pf->page > pf->end)
631 wrterror("(ES): sick entry on free_list\n");
632 if ((void*)pf->page >= (void*)sbrk(0))
633 wrterror("(ES): entry on free_list past brk\n");
634 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
635 wrterror("(ES): non-free first page on free-list\n");
636 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
637 wrterror("(ES): non-free last page on free-list\n");
638#endif /* MALLOC_EXTRA_SANITY */
639
640 if (pf->size < size)
641 continue;
642
643 if (pf->size == size) {
644 p = pf->page;
645 if (pf->next)
646 pf->next->prev = pf->prev;
647 pf->prev->next = pf->next;
648 delay_free = pf;
649 break;
193 } 650 }
194 /* remove from linked list */ 651
195 nextf[bucket] = op->ov_next; 652 p = pf->page;
196 op->ov_magic = MAGIC; 653 pf->page = (char *)pf->page + size;
197 op->ov_index = bucket; 654 pf->size -= size;
198#ifdef MSTATS 655 break;
199 nmalloc[bucket]++; 656 }
200#endif 657
201#ifdef RCHECK 658#ifdef MALLOC_EXTRA_SANITY
202 /* 659 if (p && page_dir[ptr2index(p)] != MALLOC_FREE)
203 * Record allocated size of block and 660 wrterror("(ES): allocated non-free page on free-list\n");
204 * bound space with magic numbers. 661#endif /* MALLOC_EXTRA_SANITY */
205 */ 662
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 663 size >>= malloc_pageshift;
207 op->ov_rmagic = RMAGIC; 664
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 665 /* Map new pages */
209#endif 666 if (!p)
210 return ((char *)(op + 1)); 667 p = map_pages(size);
668
669 if (p) {
670
671 index = ptr2index(p);
672 page_dir[index] = MALLOC_FIRST;
673 for (i=1;i<size;i++)
674 page_dir[index+i] = MALLOC_FOLLOW;
675
676 if (malloc_junk)
677 memset(p, SOME_JUNK, size << malloc_pageshift);
678 }
679
680 if (delay_free) {
681 if (!px)
682 px = delay_free;
683 else
684 ifree(delay_free);
685 }
686
687 return p;
211} 688}
212 689
213/* 690/*
214 * Allocate more memory to the indicated bucket. 691 * Allocate a page of fragments
215 */ 692 */
216static void 693
217morecore(bucket) 694static __inline__ int
218 int bucket; 695malloc_make_chunks(bits)
696 int bits;
219{ 697{
220 register union overhead *op; 698 struct pginfo *bp;
221 register long sz; /* size of desired block */ 699 void *pp;
222 long amt; /* amount to allocate */ 700 int i, k, l;
223 int nblks; /* how many blocks we get */
224 701
225 /* 702 /* Allocate a new bucket */
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 703 pp = malloc_pages((size_t)malloc_pagesize);
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 704 if (!pp)
228 */ 705 return 0;
229 sz = 1 << (bucket + 3); 706
230#ifdef DEBUG 707 /* Find length of admin structure */
231 ASSERT(sz > 0); 708 l = sizeof *bp - sizeof(u_long);
232#else 709 l += sizeof(u_long) *
233 if (sz <= 0) 710 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
234 return; 711
235#endif 712 /* Don't waste more than two chunks on this */
236 if (sz < pagesz) { 713 /*
237 amt = pagesz; 714 * If we are to allocate a memory protected page for the malloc(0)
238 nblks = amt / sz; 715 * case (when bits=0), it must be from a different page than the
239 } else { 716 * pginfo page.
240 amt = sz + pagesz; 717 * --> Treat it like the big chunk alloc, get a second data page.
241 nblks = 1; 718 */
719 if (bits != 0 && (1UL<<(bits)) <= l+l) {
720 bp = (struct pginfo *)pp;
721 } else {
722 bp = (struct pginfo *)imalloc(l);
723 if (!bp) {
724 ifree(pp);
725 return 0;
242 } 726 }
243 op = (union overhead *)sbrk(amt); 727 }
244 /* no more room! */ 728
245 if ((long)op == -1) 729 /* memory protect the page allocated in the malloc(0) case */
246 return; 730 if (bits == 0) {
247 /* 731
248 * Add new memory allocated to that on 732 bp->size = 0;
249 * free list for this hash bucket. 733 bp->shift = 1;
250 */ 734 i = malloc_minsize-1;
251 nextf[bucket] = op; 735 while (i >>= 1)
252 while (--nblks > 0) { 736 bp->shift++;
253 op->ov_next = (union overhead *)((caddr_t)op + sz); 737 bp->total = bp->free = malloc_pagesize >> bp->shift;
254 op = (union overhead *)((caddr_t)op + sz); 738 bp->page = pp;
255 } 739
740 k = mprotect(pp, malloc_pagesize, PROT_NONE);
741 if (k < 0) {
742 ifree(pp);
743 ifree(bp);
744 return 0;
745 }
746 } else {
747 bp->size = (1UL<<bits);
748 bp->shift = bits;
749 bp->total = bp->free = malloc_pagesize >> bits;
750 bp->page = pp;
751 }
752
753 /* set all valid bits in the bitmap */
754 k = bp->total;
755 i = 0;
756
757 /* Do a bunch at a time */
758 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
759 bp->bits[i / MALLOC_BITS] = ~0UL;
760
761 for(; i < k; i++)
762 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
763
764 if (bp == bp->page) {
765 /* Mark the ones we stole for ourselves */
766 for(i=0;l > 0;i++) {
767 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
768 bp->free--;
769 bp->total--;
770 l -= (1 << bits);
771 }
772 }
773
774 /* MALLOC_LOCK */
775
776 page_dir[ptr2index(pp)] = bp;
777
778 bp->next = page_dir[bits];
779 page_dir[bits] = bp;
780
781 /* MALLOC_UNLOCK */
782
783 return 1;
256} 784}
257 785
258void 786/*
259free(cp) 787 * Allocate a fragment
260 void *cp; 788 */
261{ 789static void *
262 register long size; 790malloc_bytes(size)
263 register union overhead *op; 791 size_t size;
264 792{
265 if (cp == NULL) 793 int i,j;
266 return; 794 u_long u;
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 795 struct pginfo *bp;
268#ifdef DEBUG 796 int k;
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 797 u_long *lp;
270#else 798
271 if (op->ov_magic != MAGIC) 799 /* Don't bother with anything less than this */
272 return; /* sanity */ 800 /* unless we have a malloc(0) requests */
273#endif 801 if (size != 0 && size < malloc_minsize)
274#ifdef RCHECK 802 size = malloc_minsize;
275 ASSERT(op->ov_rmagic == RMAGIC); 803
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 804 /* Find the right bucket */
277#endif 805 if (size == 0)
278 size = op->ov_index; 806 j=0;
279 ASSERT(size < NBUCKETS); 807 else {
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 808 j = 1;
281 nextf[size] = op; 809 i = size-1;
282#ifdef MSTATS 810 while (i >>= 1)
283 nmalloc[size]--; 811 j++;
284#endif 812 }
813
814 /* If it's empty, make a page more of that size chunks */
815 if (!page_dir[j] && !malloc_make_chunks(j))
816 return 0;
817
818 bp = page_dir[j];
819
820 /* Find first word of bitmap which isn't empty */
821 for (lp = bp->bits; !*lp; lp++)
822 ;
823
824 /* Find that bit, and tweak it */
825 u = 1;
826 k = 0;
827 while (!(*lp & u)) {
828 u += u;
829 k++;
830 }
831 *lp ^= u;
832
833 /* If there are no more free, remove from free-list */
834 if (!--bp->free) {
835 page_dir[j] = bp->next;
836 bp->next = 0;
837 }
838
839 /* Adjust to the real offset of that chunk */
840 k += (lp-bp->bits)*MALLOC_BITS;
841 k <<= bp->shift;
842
843 if (malloc_junk && bp->size != 0)
844 memset((char *)bp->page + k, SOME_JUNK, bp->size);
845
846 return (u_char *)bp->page + k;
285} 847}
286 848
287/* 849/*
288 * When a program attempts "storage compaction" as mentioned in the 850 * 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 */ 851 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 852static void *
853imalloc(size)
854 size_t size;
855{
856 void *result;
299 857
300void * 858 if (!malloc_started)
301realloc(cp, nbytes) 859 malloc_init();
302 void *cp; 860
303 size_t nbytes; 861 if (suicide)
304{ 862 abort();
305 register u_long onb; 863
306 register long i; 864 if ((size + malloc_pagesize) < size) /* Check for overflow */
307 union overhead *op; 865 result = 0;
308 char *res; 866 else if (size <= malloc_maxsize)
309 int was_alloced = 0; 867 result = malloc_bytes(size);
310 868 else
311 if (cp == NULL) 869 result = malloc_pages(size);
312 return (malloc(nbytes)); 870
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 871 if (malloc_abort && !result)
314 if (op->ov_magic == MAGIC) { 872 wrterror("allocation failed.\n");
315 was_alloced++; 873
316 i = op->ov_index; 874 if (malloc_zero && result)
317 } else { 875 memset(result, 0, size);
318 /* 876
319 * Already free, doing "compaction". 877 return result;
320 * 878}
321 * Search for the old block of memory on the 879
322 * free list. First, check the most common 880/*
323 * case (last element free'd), then (this failing) 881 * Change the size of an allocation.
324 * the last ``realloc_srchlen'' items free'd. 882 */
325 * If all lookups fail, then assume the size of 883static void *
326 * the memory block being realloc'd is the 884irealloc(ptr, size)
327 * largest possible (so that all "nbytes" of new 885 void *ptr;
328 * memory are copied into). Note that this could cause 886 size_t size;
329 * a memory fault if the old area was tiny, and the moon 887{
330 * is gibbous. However, that is very unlikely. 888 void *p;
331 */ 889 u_long osize, index;
332 if ((i = findbucket(op, 1)) < 0 && 890 struct pginfo **mp;
333 (i = findbucket(op, realloc_srchlen)) < 0) 891 int i;
334 i = NBUCKETS; 892
893 if (suicide)
894 abort();
895
896 if (!malloc_started) {
897 wrtwarning("malloc() has never been called.\n");
898 return 0;
899 }
900
901 index = ptr2index(ptr);
902
903 if (index < malloc_pageshift) {
904 wrtwarning("junk pointer, too low to make sense.\n");
905 return 0;
906 }
907
908 if (index > last_index) {
909 wrtwarning("junk pointer, too high to make sense.\n");
910 return 0;
911 }
912
913 mp = &page_dir[index];
914
915 if (*mp == MALLOC_FIRST) { /* Page allocation */
916
917 /* Check the pointer */
918 if ((u_long)ptr & malloc_pagemask) {
919 wrtwarning("modified (page-) pointer.\n");
920 return 0;
335 } 921 }
336 onb = 1 << (i + 3); 922
337 if (onb < pagesz) 923 /* Find the size in bytes */
338 onb -= sizeof (*op) + RSLOP; 924 for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
339 else 925 osize += malloc_pagesize;
340 onb += pagesz - sizeof (*op) - RSLOP; 926
341 /* avoid the copy if same size block */ 927 if (!malloc_realloc && /* unless we have to, */
342 if (was_alloced) { 928 size <= osize && /* .. or are too small, */
343 if (i) { 929 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
344 i = 1 << (i + 2); 930 return ptr; /* don't do anything. */
345 if (i < pagesz) 931 }
346 i -= sizeof (*op) + RSLOP; 932
347 else 933 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
348 i += pagesz - sizeof (*op) - RSLOP; 934
349 } 935 /* Check the pointer for sane values */
350 if (nbytes <= onb && nbytes > i) { 936 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
351#ifdef RCHECK 937 wrtwarning("modified (chunk-) pointer.\n");
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 938 return 0;
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 939 }
354#endif 940
355 return(cp); 941 /* Find the chunk index in the page */
356 } else 942 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
357 free(cp); 943
944 /* Verify that it isn't a free chunk already */
945 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
946 wrtwarning("chunk is already free.\n");
947 return 0;
358 } 948 }
359 if ((res = malloc(nbytes)) == NULL) 949
360 return (NULL); 950 osize = (*mp)->size;
361 if (cp != res) /* common optimization if "compacting" */ 951
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb); 952 if (!malloc_realloc && /* Unless we have to, */
363 return (res); 953 size < osize && /* ..or are too small, */
954 (size > osize/2 || /* ..or could use a smaller size, */
955 osize == malloc_minsize)) { /* ..(if there is one) */
956 return ptr; /* ..Don't do anything */
957 }
958
959 } else {
960 wrtwarning("pointer to wrong page.\n");
961 return 0;
962 }
963
964 p = imalloc(size);
965
966 if (p) {
967 /* copy the lesser of the two sizes, and free the old one */
968 /* Don't move from/to 0 sized region !!! */
969 if (osize != 0 && size != 0) {
970 if (osize < size)
971 memcpy(p, ptr, osize);
972 else
973 memcpy(p, ptr, size);
974 }
975 ifree(ptr);
976 }
977 return p;
364} 978}
365 979
366/* 980/*
367 * Search ``srchlen'' elements of each free list for a block whose 981 * 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 */ 982 */
371static 983
372findbucket(freep, srchlen) 984static __inline__ void
373 union overhead *freep; 985free_pages(ptr, index, info)
374 int srchlen; 986 void *ptr;
987 int index;
988 struct pginfo *info;
375{ 989{
376 register union overhead *p; 990 int i;
377 register int i, j; 991 struct pgfree *pf, *pt=0;
378 992 u_long l;
379 for (i = 0; i < NBUCKETS; i++) { 993 void *tail;
380 j = 0; 994
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 995 if (info == MALLOC_FREE) {
382 if (p == freep) 996 wrtwarning("page is already free.\n");
383 return (i); 997 return;
384 j++; 998 }
385 } 999
1000 if (info != MALLOC_FIRST) {
1001 wrtwarning("pointer to wrong page.\n");
1002 return;
1003 }
1004
1005 if ((u_long)ptr & malloc_pagemask) {
1006 wrtwarning("modified (page-) pointer.\n");
1007 return;
1008 }
1009
1010 /* Count how many pages and mark them free at the same time */
1011 page_dir[index] = MALLOC_FREE;
1012 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
1013 page_dir[index + i] = MALLOC_FREE;
1014
1015 l = i << malloc_pageshift;
1016
1017 if (malloc_junk)
1018 memset(ptr, SOME_JUNK, l);
1019
1020#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1021 if (malloc_hint)
1022 madvise(ptr, l, MADV_FREE);
1023#endif
1024
1025 tail = (char *)ptr+l;
1026
1027 /* add to free-list */
1028 if (!px)
1029 px = imalloc(sizeof *px); /* This cannot fail... */
1030 px->page = ptr;
1031 px->end = tail;
1032 px->size = l;
1033 if (!free_list.next) {
1034
1035 /* Nothing on free list, put this at head */
1036 px->next = free_list.next;
1037 px->prev = &free_list;
1038 free_list.next = px;
1039 pf = px;
1040 px = 0;
1041
1042 } else {
1043
1044 /* Find the right spot, leave pf pointing to the modified entry. */
1045 tail = (char *)ptr+l;
1046
1047 for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next)
1048 ; /* Race ahead here */
1049
1050 if (pf->page > tail) {
1051 /* Insert before entry */
1052 px->next = pf;
1053 px->prev = pf->prev;
1054 pf->prev = px;
1055 px->prev->next = px;
1056 pf = px;
1057 px = 0;
1058 } else if (pf->end == ptr ) {
1059 /* Append to the previous entry */
1060 pf->end = (char *)pf->end + l;
1061 pf->size += l;
1062 if (pf->next && pf->end == pf->next->page ) {
1063 /* And collapse the next too. */
1064 pt = pf->next;
1065 pf->end = pt->end;
1066 pf->size += pt->size;
1067 pf->next = pt->next;
1068 if (pf->next)
1069 pf->next->prev = pf;
1070 }
1071 } else if (pf->page == tail) {
1072 /* Prepend to entry */
1073 pf->size += l;
1074 pf->page = ptr;
1075 } else if (!pf->next) {
1076 /* Append at tail of chain */
1077 px->next = 0;
1078 px->prev = pf;
1079 pf->next = px;
1080 pf = px;
1081 px = 0;
1082 } else {
1083 wrterror("freelist is destroyed.\n");
386 } 1084 }
387 return (-1); 1085 }
1086
1087 /* Return something to OS ? */
1088 if (!pf->next && /* If we're the last one, */
1089 pf->size > malloc_cache && /* ..and the cache is full, */
1090 pf->end == malloc_brk && /* ..and none behind us, */
1091 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1092
1093 /*
1094 * Keep the cache intact. Notice that the '>' above guarantees that
1095 * the pf will always have at least one page afterwards.
1096 */
1097 pf->end = (char *)pf->page + malloc_cache;
1098 pf->size = malloc_cache;
1099
1100 brk(pf->end);
1101 malloc_brk = pf->end;
1102
1103 index = ptr2index(pf->end);
1104 last_index = index - 1;
1105
1106 for(i=index;i <= last_index;)
1107 page_dir[i++] = MALLOC_NOT_MINE;
1108
1109 /* XXX: We could realloc/shrink the pagedir here I guess. */
1110 }
1111 if (pt)
1112 ifree(pt);
388} 1113}
389 1114
390#ifdef MSTATS
391/* 1115/*
392 * mstats - print out statistics about malloc 1116 * 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 */ 1117 */
398mstats(s) 1118
399 char *s; 1119/* ARGSUSED */
1120static __inline__ void
1121free_bytes(ptr, index, info)
1122 void *ptr;
1123 int index;
1124 struct pginfo *info;
400{ 1125{
401 register int i, j; 1126 int i;
402 register union overhead *p; 1127 struct pginfo **mp;
403 int totfree = 0, 1128 void *vp;
404 totused = 0; 1129
405 1130 /* Find the chunk number on the page */
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1131 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
407 for (i = 0; i < NBUCKETS; i++) { 1132
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1133 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
409 ; 1134 wrtwarning("modified (chunk-) pointer.\n");
410 fprintf(stderr, " %d", j); 1135 return;
411 totfree += j * (1 << (i + 3)); 1136 }
412 } 1137
413 fprintf(stderr, "\nused:\t"); 1138 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
414 for (i = 0; i < NBUCKETS; i++) { 1139 wrtwarning("chunk is already free.\n");
415 fprintf(stderr, " %d", nmalloc[i]); 1140 return;
416 totused += nmalloc[i] * (1 << (i + 3)); 1141 }
417 } 1142
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1143 if (malloc_junk && info->size != 0)
419 totused, totfree); 1144 memset(ptr, SOME_JUNK, info->size);
1145
1146 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1147 info->free++;
1148
1149 if (info->size != 0)
1150 mp = page_dir + info->shift;
1151 else
1152 mp = page_dir;
1153
1154 if (info->free == 1) {
1155
1156 /* Page became non-full */
1157
1158 /* Insert in address order */
1159 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1160 mp = &(*mp)->next;
1161 info->next = *mp;
1162 *mp = info;
1163 return;
1164 }
1165
1166 if (info->free != info->total)
1167 return;
1168
1169 /* Find & remove this page in the queue */
1170 while (*mp != info) {
1171 mp = &((*mp)->next);
1172#ifdef MALLOC_EXTRA_SANITY
1173 if (!*mp)
1174 wrterror("(ES): Not on queue\n");
1175#endif /* MALLOC_EXTRA_SANITY */
1176 }
1177 *mp = info->next;
1178
1179 /* Free the page & the info structure if need be */
1180 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1181
1182 /* If the page was mprotected, unprotect it before releasing it */
1183 if (info->size == 0) {
1184 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1185 /* Do we have to care if mprotect succeeds here ? */
1186 }
1187
1188 vp = info->page; /* Order is important ! */
1189 if(vp != (void*)info)
1190 ifree(info);
1191 ifree(vp);
1192}
1193
1194static void
1195ifree(ptr)
1196 void *ptr;
1197{
1198 struct pginfo *info;
1199 int index;
1200
1201 /* This is legal */
1202 if (!ptr)
1203 return;
1204
1205 if (!malloc_started) {
1206 wrtwarning("malloc() has never been called.\n");
1207 return;
1208 }
1209
1210 /* If we're already sinking, don't make matters any worse. */
1211 if (suicide)
1212 return;
1213
1214 index = ptr2index(ptr);
1215
1216 if (index < malloc_pageshift) {
1217 wrtwarning("junk pointer, too low to make sense.\n");
1218 return;
1219 }
1220
1221 if (index > last_index) {
1222 wrtwarning("junk pointer, too high to make sense.\n");
1223 return;
1224 }
1225
1226 info = page_dir[index];
1227
1228 if (info < MALLOC_MAGIC)
1229 free_pages(ptr, index, info);
1230 else
1231 free_bytes(ptr, index, info);
1232 return;
1233}
1234
1235/*
1236 * These are the public exported interface routines.
1237 */
1238
1239static int malloc_active;
1240
1241void *
1242malloc(size_t size)
1243{
1244 register void *r;
1245
1246 malloc_func = " in malloc():";
1247 THREAD_LOCK();
1248 if (malloc_active++) {
1249 wrtwarning("recursive call.\n");
1250 malloc_active--;
1251 THREAD_UNLOCK();
1252 return (0);
1253 }
1254 r = imalloc(size);
1255 UTRACE(0, size, r);
1256 malloc_active--;
1257 THREAD_UNLOCK();
1258 if (malloc_xmalloc && !r)
1259 wrterror("out of memory.\n");
1260 return (r);
1261}
1262
1263void
1264free(void *ptr)
1265{
1266 malloc_func = " in free():";
1267 THREAD_LOCK();
1268 if (malloc_active++) {
1269 wrtwarning("recursive call.\n");
1270 malloc_active--;
1271 THREAD_UNLOCK();
1272 return;
1273 }
1274 ifree(ptr);
1275 UTRACE(ptr, 0, 0);
1276 malloc_active--;
1277 THREAD_UNLOCK();
1278 return;
1279}
1280
1281void *
1282realloc(void *ptr, size_t size)
1283{
1284 register void *r;
1285
1286 malloc_func = " in realloc():";
1287 THREAD_LOCK();
1288 if (malloc_active++) {
1289 wrtwarning("recursive call.\n");
1290 malloc_active--;
1291 THREAD_UNLOCK();
1292 return (0);
1293 }
1294 if (!ptr) {
1295 r = imalloc(size);
1296 } else {
1297 r = irealloc(ptr, size);
1298 }
1299 UTRACE(ptr, size, r);
1300 malloc_active--;
1301 THREAD_UNLOCK();
1302 if (malloc_xmalloc && !r)
1303 wrterror("out of memory.\n");
1304 return (r);
420} 1305}
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..6c4eba46bf 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.9 2002/02/23 19:51:46 miod 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.
@@ -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..31a4fdf4dd 100644
--- a/src/lib/libc/stdlib/rand48.3
+++ b/src/lib/libc/stdlib/rand48.3
@@ -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.8 2001/08/06 10:42:26 mpech Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd October 8, 1993
15.Dt RAND48 3 15.Dt RAND48 3
@@ -27,7 +27,7 @@
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,7 +64,8 @@ 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
@@ -71,7 +73,8 @@ such that the values produced lie in the interval [0.0, 1.0).
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
@@ -153,8 +157,9 @@ generator 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..3d4545651b 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.14 2001/09/06 15:04:34 mpech 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
68.Fn srandom
69functions have (almost) the same calling sequence and initialization
70properties as
70.Xr rand 3 Ns / Xr srand 3 . 71.Xr rand 3 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 initialize 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..5ce7c90ee9 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,15 @@
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.9 2000/04/04 14:27:00 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/types.h>
39#include <sys/time.h>
40#include <fcntl.h>
39#include <stdio.h> 41#include <stdio.h>
40#include <stdlib.h> 42#include <stdlib.h>
43#include <unistd.h>
41 44
42/* 45/*
43 * random.c: 46 * random.c:
@@ -136,12 +139,12 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
136 139
137static long randtbl[DEG_3 + 1] = { 140static long randtbl[DEG_3 + 1] = {
138 TYPE_3, 141 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 142 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 143 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 144 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 145 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 146 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 147 0xf3bec5da,
145}; 148};
146 149
147/* 150/*
@@ -193,15 +196,26 @@ void
193srandom(x) 196srandom(x)
194 u_int x; 197 u_int x;
195{ 198{
196 register int i, j; 199 register long int test;
200 register int i;
201 ldiv_t val;
197 202
198 if (rand_type == TYPE_0) 203 if (rand_type == TYPE_0)
199 state[0] = x; 204 state[0] = x;
200 else { 205 else {
201 j = 1;
202 state[0] = x; 206 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 207 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 208 /*
209 * Implement the following, without overflowing 31 bits:
210 *
211 * state[i] = (16807 * state[i - 1]) % 2147483647;
212 *
213 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
214 */
215 val = ldiv(state[i-1], 127773);
216 test = 16807 * val.rem - 2836 * val.quot;
217 state[i] = test + (test < 0 ? 2147483647 : 0);
218 }
205 fptr = &state[rand_sep]; 219 fptr = &state[rand_sep];
206 rptr = &state[0]; 220 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 221 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +224,49 @@ srandom(x)
210} 224}
211 225
212/* 226/*
227 * srandomdev:
228 *
229 * Many programs choose the seed value in a totally predictable manner.
230 * This often causes problems. We seed the generator using the much more
231 * secure arandom(4) interface. Note that this particular seeding
232 * procedure can generate states which are impossible to reproduce by
233 * calling srandom() with any value, since the succeeding terms in the
234 * state buffer are no longer derived from the LC algorithm applied to
235 * a fixed seed.
236 */
237void
238srandomdev()
239{
240 int fd;
241 size_t len;
242
243 if (rand_type == TYPE_0)
244 len = sizeof(state[0]);
245 else
246 len = rand_deg * sizeof(state[0]);
247
248 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
249 read(fd, (void *) state, len) == (ssize_t) len) {
250 close(fd);
251 } else {
252 struct timeval tv;
253 u_int junk;
254
255 /* XXX - this could be better */
256 gettimeofday(&tv, NULL);
257 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
258 if (fd != -1)
259 close(fd);
260 return;
261 }
262
263 if (rand_type != TYPE_0) {
264 fptr = &state[rand_sep];
265 rptr = &state[0];
266 }
267}
268
269/*
213 * initstate: 270 * initstate:
214 * 271 *
215 * Initialize the state information in the given array of n bytes for future 272 * Initialize the state information in the given array of n bytes for future
@@ -232,7 +289,7 @@ char *
232initstate(seed, arg_state, n) 289initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 290 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 291 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 292 size_t n; /* # bytes of state info */
236{ 293{
237 register char *ostate = (char *)(&state[-1]); 294 register char *ostate = (char *)(&state[-1]);
238 295
@@ -240,11 +297,8 @@ initstate(seed, arg_state, n)
240 state[-1] = rand_type; 297 state[-1] = rand_type;
241 else 298 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 299 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 300 if (n < BREAK_0)
244 (void)fprintf(stderr, 301 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 302 if (n < BREAK_1) {
249 rand_type = TYPE_0; 303 rand_type = TYPE_0;
250 rand_deg = DEG_0; 304 rand_deg = DEG_0;
@@ -293,7 +347,7 @@ initstate(seed, arg_state, n)
293 */ 347 */
294char * 348char *
295setstate(arg_state) 349setstate(arg_state)
296 char *arg_state; 350 const char *arg_state;
297{ 351{
298 register long *new_state = (long *)arg_state; 352 register long *new_state = (long *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 353 register int type = new_state[0] % MAX_TYPES;
@@ -315,8 +369,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 369 rand_sep = seps[type];
316 break; 370 break;
317 default: 371 default:
318 (void)fprintf(stderr, 372 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 373 }
321 state = &new_state[1]; 374 state = &new_state[1];
322 if (rand_type != TYPE_0) { 375 if (rand_type != TYPE_0) {
diff --git a/src/lib/libc/stdlib/realloc.3 b/src/lib/libc/stdlib/realloc.3
deleted file mode 100644
index 66f09b2081..0000000000
--- a/src/lib/libc/stdlib/realloc.3
+++ /dev/null
@@ -1,100 +0,0 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
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. All advertising materials mentioning features or use of this software
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" from: @(#)realloc.3 5.1 (Berkeley) 5/2/91
33.\" $Id: realloc.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\"
35.Dd May 2, 1991
36.Dt REALLOC 3
37.Os
38.Sh NAME
39.Nm realloc
40.Nd reallocation of memory function
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft void *
44.Fn realloc "void *ptr" "size_t size"
45.Sh DESCRIPTION
46The
47.Fn realloc
48function changes the size of the object pointed to by
49.Fa ptr
50to the size specified by
51.Fa size .
52The contents of the object are unchanged up to the lesser
53of the new and old sizes.
54If the new size is larger, the value of the newly allocated portion
55of the object is indeterminate.
56If
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
87The
88.Fn realloc
89function returns either a null pointer or a pointer
90to the possibly moved allocated space.
91.Sh SEE ALSO
92.Xr alloca 3 ,
93.Xr calloc 3 ,
94.Xr free 3 ,
95.Xr malloc 3 ,
96.Sh STANDARDS
97The
98.Fn realloc
99function conforms to
100.St -ansiC .
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..d01b19e0f2 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.7 2002/05/24 21:22:37 deraadt 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
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..fc7c67a5db 100644
--- a/src/lib/libc/stdlib/setenv.c
+++ b/src/lib/libc/stdlib/setenv.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: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/ 35static char *rcsid = "$OpenBSD: setenv.c,v 1.4 2001/07/09 06:57:45 deraadt 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>
@@ -63,7 +62,8 @@ setenv(name, value, rewrite)
63 if (!rewrite) 62 if (!rewrite)
64 return (0); 63 return (0);
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 64 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 65 while ((*C++ = *value++))
66 ;
67 return (0); 67 return (0);
68 } 68 }
69 } else { /* create new slot */ 69 } else { /* create new slot */
@@ -72,10 +72,11 @@ setenv(name, value, rewrite)
72 72
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 73 for (P = environ, cnt = 0; *P; ++P, ++cnt);
74 if (alloced) { /* just increase size */ 74 if (alloced) { /* just increase size */
75 environ = (char **)realloc((char *)environ, 75 P = (char **)realloc((void *)environ,
76 (size_t)(sizeof(char *) * (cnt + 2))); 76 (size_t)(sizeof(char *) * (cnt + 2)));
77 if (!environ) 77 if (!P)
78 return (-1); 78 return (-1);
79 environ = P;
79 } 80 }
80 else { /* get new space */ 81 else { /* get new space */
81 alloced = 1; /* copy old entries into it */ 82 alloced = 1; /* copy old entries into it */
@@ -95,7 +96,7 @@ setenv(name, value, rewrite)
95 return (-1); 96 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 97 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 98 ;
98 for (*C++ = '='; *C++ = *value++; ) 99 for (*C++ = '='; (*C++ = *value++); )
99 ; 100 ;
100 return (0); 101 return (0);
101} 102}
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..ce7ce9fe56 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.15 2002/02/19 19:39:37 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;
@@ -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..a5bdff0b81 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.10 2002/06/29 00:20:11 millert 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,13 @@ 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 sscanf 3 ,
160.Xr strtod 3 , 235.Xr strtod 3 ,
161.Xr strtoul 3 236.Xr strtoul 3
162.Sh STANDARDS 237.Sh STANDARDS
163The 238The
164.Fn strtol 239.Fn strtol
165function 240function conforms to
166conforms to
167.St -ansiC . 241.St -ansiC .
168.Sh BUGS 242.Sh BUGS
169Ignores the current locale. 243Ignores 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..6d55de4d7a 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.10 2002/06/29 00:20:11 millert 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,29 @@
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.
77.Pp 86.Pp
78The string may begin with an arbitrary amount of white space 87The string may begin with an arbitrary amount of whitespace
79(as determined by 88(as determined by
80.Xr isspace 3 ) 89.Xr isspace 3 )
81followed by a single optional 90followed by a single optional
@@ -85,26 +94,22 @@ or
85sign. 94sign.
86If 95If
87.Fa base 96.Fa base
88is zero or 16, 97is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 98.Ql 0x
91prefix, 99prefix, 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 100.Fa base
94is taken as 10 (decimal) unless the next character is 101is taken as 10 (decimal) unless the next character is
95.Ql 0 , 102.Ql 0 ,
96in which case it is taken as 8 (octal). 103in which case it is taken as 8 (octal).
97.Pp 104.Pp
98The remainder of the string is converted to an 105The remainder of the string is converted to an
99.Em unsigned long 106.Li unsigned long
100value in the obvious manner, 107value 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 108or at the first character that does not produce a valid digit
103in the given base. 109in the given base.
104(In bases above 10, the letter 110(In bases above 10, the letter
105.Ql A 111.Ql A
106in either upper or lower case 112in either upper or lower case represents 10,
107represents 10,
108.Ql B 113.Ql B
109represents 11, and so forth, with 114represents 11, and so forth, with
110.Ql Z 115.Ql Z
@@ -112,7 +117,7 @@ representing 35.)
112.Pp 117.Pp
113If 118If
114.Fa endptr 119.Fa endptr
115is non nil, 120is non-null,
116.Fn strtoul 121.Fn strtoul
117stores the address of the first invalid character in 122stores the address of the first invalid character in
118.Fa *endptr . 123.Fa *endptr .
@@ -134,12 +139,18 @@ on return, the entire string was valid.)
134.Sh RETURN VALUES 139.Sh RETURN VALUES
135The 140The
136.Fn strtoul 141.Fn strtoul
137function 142function returns the result of the conversion,
138returns either the result of the conversion 143unless the value would overflow, in which case
139or, if there was a leading minus sign, 144.Dv ULONG_MAX
140the negation of the result of the conversion, 145is returned and
141unless the original (non-negated) value would overflow; 146.Va errno
142in the latter case, 147is set to
148.Er ERANGE .
149If there was a leading minus sign,
150.Fn strtoul
151returns the (unsigned) negation of the absolute value of the number, unless
152the absolute value would overflow.
153In this case,
143.Fn strtoul 154.Fn strtoul
144returns 155returns
145.Dv ULONG_MAX 156.Dv ULONG_MAX
@@ -147,18 +158,68 @@ and sets the global variable
147.Va errno 158.Va errno
148to 159to
149.Er ERANGE . 160.Er ERANGE .
161.Pp
162The
163.Fn strtoull
164function has identical return values except that
165.Dv ULLONG_MIN
166and
167.Dv ULLONG_MAX
168are used to indicate underflow and overflow respectively.
169.Pp
170There is no way to determine if
171.Fn strtoul
172has processed a negative number (and returned an unsigned value) short of
173examining the string in
174.Fa nptr
175directly.
176.Sh EXAMPLES
177Ensuring that a string is a valid number (i.e., in range and containing no
178trailing characters) requires clearing
179.Va errno
180beforehand explicitly since
181.Va errno
182is not changed on a successful call to
183.Fn strtoul ,
184and the return value of
185.Fn strtoul
186cannot be used unambiguously to signal an error:
187.Bd -literal -offset indent
188char *ep;
189unsigned long ulval;
190
191\&...
192
193errno = 0;
194ulval = strtoul(buf, &ep, 10);
195if (buf[0] == '\e0' || *ep != '\e0')
196 goto not_a_number;
197if (errno == ERANGE && ulval == ULONG_MAX)
198 goto out_of_range;
199.Ed
200.Pp
201This example will accept
202.Dq 12
203but not
204.Dq 12foo
205or
206.Dq 12\en .
207If trailing whitespace is acceptable, further checks must be done on
208.Va *ep ;
209alternately, use
210.Xr sscanf 3 .
150.Sh ERRORS 211.Sh ERRORS
151.Bl -tag -width Er 212.Bl -tag -width Er
152.It Bq Er ERANGE 213.It Bq Er ERANGE
153The given string was out of range; the value converted has been clamped. 214The given string was out of range; the value converted has been clamped.
154.El 215.El
155.Sh SEE ALSO 216.Sh SEE ALSO
217.Xr sscanf 3 ,
156.Xr strtol 3 218.Xr strtol 3
157.Sh STANDARDS 219.Sh STANDARDS
158The 220The
159.Fn strtoul 221.Fn strtoul
160function 222function conforms to
161conforms to
162.St -ansiC . 223.St -ansiC .
163.Sh BUGS 224.Sh BUGS
164Ignores the current locale. 225Ignores 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}