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.inc63
-rw-r--r--src/lib/libc/stdlib/_Exit.c22
-rw-r--r--src/lib/libc/stdlib/_rand48.c47
-rw-r--r--src/lib/libc/stdlib/a64l.3133
-rw-r--r--src/lib/libc/stdlib/a64l.c42
-rw-r--r--src/lib/libc/stdlib/abort.368
-rw-r--r--src/lib/libc/stdlib/abort.c80
-rw-r--r--src/lib/libc/stdlib/abs.370
-rw-r--r--src/lib/libc/stdlib/abs.c37
-rw-r--r--src/lib/libc/stdlib/alloca.376
-rw-r--r--src/lib/libc/stdlib/atexit.377
-rw-r--r--src/lib/libc/stdlib/atexit.c194
-rw-r--r--src/lib/libc/stdlib/atexit.h50
-rw-r--r--src/lib/libc/stdlib/atof.374
-rw-r--r--src/lib/libc/stdlib/atof.c37
-rw-r--r--src/lib/libc/stdlib/atoi.391
-rw-r--r--src/lib/libc/stdlib/atoi.c37
-rw-r--r--src/lib/libc/stdlib/atol.370
-rw-r--r--src/lib/libc/stdlib/atol.c37
-rw-r--r--src/lib/libc/stdlib/atoll.370
-rw-r--r--src/lib/libc/stdlib/atoll.c38
-rw-r--r--src/lib/libc/stdlib/bsearch.384
-rw-r--r--src/lib/libc/stdlib/bsearch.c67
-rw-r--r--src/lib/libc/stdlib/cfree.c39
-rw-r--r--src/lib/libc/stdlib/div.364
-rw-r--r--src/lib/libc/stdlib/div.c71
-rw-r--r--src/lib/libc/stdlib/drand48.c23
-rw-r--r--src/lib/libc/stdlib/ecvt.3168
-rw-r--r--src/lib/libc/stdlib/ecvt.c106
-rw-r--r--src/lib/libc/stdlib/erand48.c24
-rw-r--r--src/lib/libc/stdlib/exit.3102
-rw-r--r--src/lib/libc/stdlib/exit.c59
-rw-r--r--src/lib/libc/stdlib/gcvt.c123
-rw-r--r--src/lib/libc/stdlib/getenv.3175
-rw-r--r--src/lib/libc/stdlib/getenv.c81
-rw-r--r--src/lib/libc/stdlib/getopt.3364
-rw-r--r--src/lib/libc/stdlib/getopt_long.3445
-rw-r--r--src/lib/libc/stdlib/getopt_long.c518
-rw-r--r--src/lib/libc/stdlib/getsubopt.3145
-rw-r--r--src/lib/libc/stdlib/getsubopt.c92
-rw-r--r--src/lib/libc/stdlib/hcreate.3239
-rw-r--r--src/lib/libc/stdlib/hcreate.c191
-rw-r--r--src/lib/libc/stdlib/heapsort.c173
-rw-r--r--src/lib/libc/stdlib/imaxabs.365
-rw-r--r--src/lib/libc/stdlib/imaxabs.c38
-rw-r--r--src/lib/libc/stdlib/imaxdiv.366
-rw-r--r--src/lib/libc/stdlib/imaxdiv.c50
-rw-r--r--src/lib/libc/stdlib/insque.3106
-rw-r--r--src/lib/libc/stdlib/insque.c48
-rw-r--r--src/lib/libc/stdlib/jrand48.c22
-rw-r--r--src/lib/libc/stdlib/l64a.c42
-rw-r--r--src/lib/libc/stdlib/labs.369
-rw-r--r--src/lib/libc/stdlib/labs.c37
-rw-r--r--src/lib/libc/stdlib/lcong48.c31
-rw-r--r--src/lib/libc/stdlib/ldiv.372
-rw-r--r--src/lib/libc/stdlib/ldiv.c50
-rw-r--r--src/lib/libc/stdlib/llabs.c38
-rw-r--r--src/lib/libc/stdlib/lldiv.366
-rw-r--r--src/lib/libc/stdlib/lldiv.c50
-rw-r--r--src/lib/libc/stdlib/lrand48.c24
-rw-r--r--src/lib/libc/stdlib/lsearch.3108
-rw-r--r--src/lib/libc/stdlib/lsearch.c84
-rw-r--r--src/lib/libc/stdlib/malloc.3484
-rw-r--r--src/lib/libc/stdlib/malloc.c1824
-rw-r--r--src/lib/libc/stdlib/merge.c333
-rw-r--r--src/lib/libc/stdlib/mrand48.c24
-rw-r--r--src/lib/libc/stdlib/nrand48.c22
-rw-r--r--src/lib/libc/stdlib/posix_memalign.392
-rw-r--r--src/lib/libc/stdlib/posix_openpt.3102
-rw-r--r--src/lib/libc/stdlib/posix_pty.c119
-rw-r--r--src/lib/libc/stdlib/ptsname.3160
-rw-r--r--src/lib/libc/stdlib/qabs.356
-rw-r--r--src/lib/libc/stdlib/qabs.c37
-rw-r--r--src/lib/libc/stdlib/qdiv.361
-rw-r--r--src/lib/libc/stdlib/qdiv.c50
-rw-r--r--src/lib/libc/stdlib/qsort.3238
-rw-r--r--src/lib/libc/stdlib/qsort.c162
-rw-r--r--src/lib/libc/stdlib/radixsort.3155
-rw-r--r--src/lib/libc/stdlib/radixsort.c294
-rw-r--r--src/lib/libc/stdlib/rand.3105
-rw-r--r--src/lib/libc/stdlib/rand.c67
-rw-r--r--src/lib/libc/stdlib/rand48.3179
-rw-r--r--src/lib/libc/stdlib/rand48.h32
-rw-r--r--src/lib/libc/stdlib/random.3185
-rw-r--r--src/lib/libc/stdlib/random.c446
-rw-r--r--src/lib/libc/stdlib/realpath.3130
-rw-r--r--src/lib/libc/stdlib/realpath.c214
-rw-r--r--src/lib/libc/stdlib/remque.c44
-rw-r--r--src/lib/libc/stdlib/seed48.c37
-rw-r--r--src/lib/libc/stdlib/setenv.c180
-rw-r--r--src/lib/libc/stdlib/srand48.c31
-rw-r--r--src/lib/libc/stdlib/strtod.3167
-rw-r--r--src/lib/libc/stdlib/strtoimax.c140
-rw-r--r--src/lib/libc/stdlib/strtol.3264
-rw-r--r--src/lib/libc/stdlib/strtol.c151
-rw-r--r--src/lib/libc/stdlib/strtoll.c144
-rw-r--r--src/lib/libc/stdlib/strtonum.3152
-rw-r--r--src/lib/libc/stdlib/strtonum.c65
-rw-r--r--src/lib/libc/stdlib/strtoul.3245
-rw-r--r--src/lib/libc/stdlib/strtoul.c102
-rw-r--r--src/lib/libc/stdlib/strtoull.c106
-rw-r--r--src/lib/libc/stdlib/strtoumax.c102
-rw-r--r--src/lib/libc/stdlib/system.3109
-rw-r--r--src/lib/libc/stdlib/system.c74
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3130
-rw-r--r--src/lib/libc/stdlib/tsearch.c119
107 files changed, 13806 insertions, 0 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
new file mode 100644
index 0000000000..953c53382f
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,63 @@
1# $OpenBSD: Makefile.inc,v 1.49 2014/03/18 22:36:29 miod Exp $
2
3# stdlib sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib
5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \
9 lldiv.c lsearch.c malloc.c merge.c posix_pty.c qsort.c radixsort.c \
10 rand.c random.c realpath.c setenv.c strtoimax.c strtol.c \
11 strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c system.c \
12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c
14
15.if (${MACHINE_CPU} == "i386")
16SRCS+= abs.S div.S labs.S ldiv.S
17.elif (${MACHINE_CPU} == "vax")
18SRCS+= abs.c div.c labs.c ldiv.c
19.elif (${MACHINE_CPU} == "alpha")
20# XXX should be .S's
21SRCS+= abs.c div.c labs.c ldiv.c
22.else
23SRCS+= abs.c div.c labs.c ldiv.c
24.endif
25
26.if (${MACHINE_CPU} == "vax")
27SRCS+= insque.S remque.S
28.else
29SRCS+= insque.c remque.c
30.endif
31
32MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
33 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
34 getsubopt.3 hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 \
35 lldiv.3 lsearch.3 malloc.3 posix_memalign.3 posix_openpt.3 ptsname.3 \
36 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
37 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3
38
39MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
40MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
41MLINKS+=getopt_long.3 getopt_long_only.3
42MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
43MLINKS+=insque.3 remque.3
44MLINKS+=labs.3 llabs.3
45MLINKS+=lsearch.3 lfind.3
46MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
47MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
48MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
49MLINKS+=radixsort.3 sradixsort.3
50MLINKS+=rand.3 srand.3 rand.3 rand_r.3
51MLINKS+=random.3 initstate.3 random.3 setstate.3
52MLINKS+=random.3 srandom.3 random.3 srandomdev.3
53MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
54MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
55MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
56MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3
57MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3
58MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3
59MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3
60MLINKS+=tsearch.3 tfind.3
61MLINKS+=tsearch.3 tdelete.3
62MLINKS+=tsearch.3 twalk.3
63MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_Exit.c b/src/lib/libc/stdlib/_Exit.c
new file mode 100644
index 0000000000..ccf64c2e87
--- /dev/null
+++ b/src/lib/libc/stdlib/_Exit.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: _Exit.c,v 1.3 2013/04/03 03:39:29 guenther Exp $ */
2
3/*
4 * Placed in the public domain by Todd C. Miller on January 21, 2004.
5 */
6
7#include <stdlib.h>
8#include <unistd.h>
9
10/*
11 * _Exit() is the ISO/ANSI C99 equivalent of the POSIX _exit() function.
12 * No atexit() handlers are called and no signal handlers are run.
13 * Whether or not stdio buffers are flushed or temporary files are removed
14 * is implementation-dependent in C99. Indeed, POSIX specifies that
15 * _Exit() must *not* flush stdio buffers or remove temporary files, but
16 * rather must behave exactly like _exit()
17 */
18void
19_Exit(int status)
20{
21 _exit(status);
22}
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
new file mode 100644
index 0000000000..7c950f7cee
--- /dev/null
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -0,0 +1,47 @@
1/* $OpenBSD: _rand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17unsigned short __rand48_seed[3] = {
18 RAND48_SEED_0,
19 RAND48_SEED_1,
20 RAND48_SEED_2
21};
22unsigned short __rand48_mult[3] = {
23 RAND48_MULT_0,
24 RAND48_MULT_1,
25 RAND48_MULT_2
26};
27unsigned short __rand48_add = RAND48_ADD;
28
29void
30__dorand48(unsigned short xseed[3])
31{
32 unsigned long accu;
33 unsigned short temp[2];
34
35 accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
36 (unsigned long) __rand48_add;
37 temp[0] = (unsigned short) accu; /* lower 16 bits */
38 accu >>= sizeof(unsigned short) * 8;
39 accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
40 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
41 temp[1] = (unsigned short) accu; /* middle 16 bits */
42 accu >>= sizeof(unsigned short) * 8;
43 accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
44 xseed[0] = temp[0];
45 xseed[1] = temp[1];
46 xseed[2] = (unsigned short) accu;
47}
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..11a74604ac
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.12 2013/06/05 03:39:23 tedu Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: June 5 2013 $
18.Dt A64L 3
19.Os
20.Sh NAME
21.Nm a64l ,
22.Nm l64a
23.Nd convert between 32-bit integer and radix-64 ASCII string
24.Sh SYNOPSIS
25.In stdlib.h
26.Ft long
27.Fn a64l "const char *s"
28.Ft char *
29.Fn l64a "long l"
30.Sh DESCRIPTION
31The
32.Fn a64l
33and
34.Fn l64a
35functions are used to maintain numbers stored in radix-64
36.Tn ASCII
37characters.
38This is a notation by which 32-bit integers
39can be represented by up to six characters; each character represents a
40.Dq digit
41in a radix-64 notation.
42.Pp
43The characters used to represent digits are
44.Ql \&.
45for 0,
46.Ql /
47for 1,
48.Ql 0
49through
50.Ql 9
51for 2-11,
52.Ql A
53through
54.Ql Z
55for 12-37, and
56.Ql a
57through
58.Ql z
59for 38-63.
60.Pp
61The
62.Fn a64l
63function takes a pointer to a NUL-terminated radix-64 representation
64and returns a corresponding 32-bit value.
65If the string pointed to by
66.Fa s
67contains more than six characters,
68.Fn a64l
69will use the first six.
70.Fn a64l
71scans the character string from left to right, decoding
72each character as a 6-bit radix-64 number.
73If a long integer is
74larger than 32 bits, the return value will be sign-extended.
75.Pp
76.Fn l64a
77takes a long integer argument
78.Fa l
79and returns a pointer to the corresponding radix-64 representation.
80.Sh RETURN VALUES
81On success,
82.Fn a64l
83returns a 32-bit representation of
84.Fa s .
85If
86.Fa s
87is a null pointer or if it contains digits other than those described above,
88.Fn a64l
89returns \-1 and sets the global variable
90.Va errno
91to
92.Er EINVAL .
93.Pp
94On success,
95.Fn l64a
96returns a pointer to a string containing the radix-64 representation of
97.Fa l .
98If
99.Fa l
100is 0,
101.Fn l64a
102returns a pointer to the empty string.
103If
104.Fa l
105is negative,
106.Fn l64a
107returns a null pointer and sets the global variable
108.Va errno
109to
110.Er EINVAL .
111.Sh STANDARDS
112The
113.Fn a64l
114and
115.Fn l64a
116functions conform to
117.St -xpg4.2 .
118.Sh CAVEATS
119The value returned by
120.Fn l64a
121is a pointer into a static buffer, the contents of which
122will be overwritten by subsequent calls.
123.Pp
124The value returned by
125.Fn a64l
126may be incorrect if the value is too large; for that reason, only strings
127that resulted from a call to
128.Fn l64a
129should be used to call
130.Fn a64l .
131.Pp
132If a long integer is larger than 32 bits, only the low-order
13332 bits are used.
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
new file mode 100644
index 0000000000..5312929c6f
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: a64l.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <errno.h>
8#include <stdlib.h>
9
10long
11a64l(const char *s)
12{
13 long value, digit, shift;
14 int i;
15
16 if (s == NULL) {
17 errno = EINVAL;
18 return(-1L);
19 }
20
21 value = 0;
22 shift = 0;
23 for (i = 0; *s && i < 6; i++, s++) {
24 if (*s >= '.' && *s <= '/')
25 digit = *s - '.';
26 else if (*s >= '0' && *s <= '9')
27 digit = *s - '0' + 2;
28 else if (*s >= 'A' && *s <= 'Z')
29 digit = *s - 'A' + 12;
30 else if (*s >= 'a' && *s <= 'z')
31 digit = *s - 'a' + 38;
32 else {
33 errno = EINVAL;
34 return(-1L);
35 }
36
37 value |= digit << shift;
38 shift += 6;
39 }
40
41 return(value);
42}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
new file mode 100644
index 0000000000..322d629930
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.3
@@ -0,0 +1,68 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: abort.3,v 1.10 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt ABORT 3
36.Os
37.Sh NAME
38.Nm abort
39.Nd cause abnormal program termination
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft void
43.Fn abort void
44.Sh DESCRIPTION
45The
46.Fn abort
47function causes abnormal program termination to occur, unless the signal
48.Dv SIGABRT
49is being caught and the signal handler does not return.
50.Pp
51Any open streams are flushed and closed.
52.Sh RETURN VALUES
53The
54.Fn abort
55function never returns.
56.Sh SEE ALSO
57.Xr sigaction 2 ,
58.Xr exit 3
59.Sh STANDARDS
60The
61.Fn abort
62function conforms to
63.St -p1003.1-90 .
64.Sh HISTORY
65The
66.Fn abort
67function first appeared in
68.At v5 .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
new file mode 100644
index 0000000000..4c8dc70a1d
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,80 @@
1/* $OpenBSD: abort.c,v 1.16 2012/11/10 03:46:11 guenther Exp $ */
2/*
3 * Copyright (c) 1985 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <signal.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include "thread_private.h"
35#include "atexit.h"
36
37int _thread_sys_sigprocmask(int, const sigset_t *, sigset_t *);
38
39void
40abort(void)
41{
42 struct atexit *p = __atexit;
43 static int cleanup_called = 0;
44 sigset_t mask;
45
46
47 sigfillset(&mask);
48 /*
49 * don't block SIGABRT to give any handler a chance; we ignore
50 * any errors -- X311J doesn't allow abort to return anyway.
51 */
52 sigdelset(&mask, SIGABRT);
53 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
54
55 /*
56 * POSIX requires we flush stdio buffers on abort
57 */
58 if (cleanup_called == 0) {
59 /* the cleanup routine lives in fns[0] on the last page */
60 while (p != NULL && p->next != NULL)
61 p = p->next;
62 /* the check for fn_dso == NULL is mostly paranoia */
63 if (p != NULL && p->fns[0].fn_dso == NULL &&
64 p->fns[0].fn_ptr.std_func != NULL) {
65 cleanup_called = 1;
66 (*p->fns[0].fn_ptr.std_func)();
67 }
68 }
69
70 (void)raise(SIGABRT);
71
72 /*
73 * if SIGABRT ignored, or caught and the handler returns, do
74 * it again, only harder.
75 */
76 (void)signal(SIGABRT, SIG_DFL);
77 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
78 (void)raise(SIGABRT);
79 _exit(1);
80}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..420bdf6fdf
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: abs.3,v 1.11 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt ABS 3
36.Os
37.Sh NAME
38.Nm abs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft int
43.Fn abs "int j"
44.Sh DESCRIPTION
45The
46.Fn abs
47function computes the absolute value of the integer
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn abs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr cabs 3 ,
55.Xr floor 3 ,
56.Xr hypot 3 ,
57.Xr imaxabs 3 ,
58.Xr labs 3
59.Sh STANDARDS
60The
61.Fn abs
62function conforms to
63.St -ansiC .
64.Sh HISTORY
65The
66.Fn abs
67function first appeared in
68.At v6 .
69.Sh BUGS
70The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
new file mode 100644
index 0000000000..5d2fbae69f
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: abs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33int
34abs(int j)
35{
36 return(j < 0 ? -j : j);
37}
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
new file mode 100644
index 0000000000..47e9b97143
--- /dev/null
+++ b/src/lib/libc/stdlib/alloca.3
@@ -0,0 +1,76 @@
1.\" Copyright (c) 1980, 1991 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. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: alloca.3,v 1.13 2013/06/05 03:39:23 tedu Exp $
29.\"
30.Dd $Mdocdate: June 5 2013 $
31.Dt ALLOCA 3
32.Os
33.Sh NAME
34.Nm alloca
35.Nd memory allocator
36.Sh SYNOPSIS
37.In stdlib.h
38.Ft void *
39.Fn alloca "size_t size"
40.Sh DESCRIPTION
41The
42.Fn alloca
43function allocates
44.Fa size
45bytes of space in the stack frame of the caller.
46This temporary space is automatically freed on return.
47.Sh RETURN VALUES
48The
49.Fn alloca
50function returns a pointer to the beginning of the allocated space.
51.Sh SEE ALSO
52.Xr pagesize 1 ,
53.Xr brk 2 ,
54.Xr calloc 3 ,
55.Xr malloc 3 ,
56.Xr realloc 3
57.\" .Sh HISTORY
58.\" The
59.\" .Fn alloca
60.\" function appeared in
61.\" .Bx ?? .
62.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
63.\" The first man page (or link to a man page that I can find at the
64.\" moment is 4.3...
65.Sh BUGS
66The
67.Fn alloca
68function is slightly unsafe because it cannot ensure that the pointer
69returned points to a valid and usable block of memory.
70The allocation made may exceed the bounds of the stack, or even go
71further into other objects in memory, and
72.Fn alloca
73cannot determine such an error.
74Avoid
75.Fn alloca
76with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
new file mode 100644
index 0000000000..8e3ac3e60f
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.3
@@ -0,0 +1,77 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: atexit.3,v 1.9 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt ATEXIT 3
36.Os
37.Sh NAME
38.Nm atexit
39.Nd register a function to be called on exit
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft int
43.Fn atexit "void (*function)(void)"
44.Sh DESCRIPTION
45The
46.Fn atexit
47function registers the given
48.Fa function
49to be called at program exit, whether via
50.Xr exit 3
51or via return from the program's
52.Fn main .
53Functions so registered are called in reverse order;
54no arguments are passed.
55At least 32 functions can always be registered,
56and more are allowed as long as sufficient memory can be allocated.
57.Pp
58.Fn atexit
59is very difficult to use correctly without creating
60.Xr exit 3 Ns -time
61races.
62Unless absolutely necessary, please avoid using it.
63.Sh RETURN VALUES
64.Rv -std atexit
65.Sh ERRORS
66.Bl -tag -width Er
67.It Bq Er ENOMEM
68No memory was available to add the function to the list.
69The existing list of functions is unmodified.
70.El
71.Sh SEE ALSO
72.Xr exit 3
73.Sh STANDARDS
74The
75.Fn atexit
76function conforms to
77.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000000..049da3261d
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,194 @@
1/* $OpenBSD: atexit.c,v 1.17 2013/12/28 18:38:42 kettenis Exp $ */
2/*
3 * Copyright (c) 2002 Daniel Hartmeier
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include "atexit.h"
38#include "thread_private.h"
39
40struct atexit *__atexit;
41
42/*
43 * Function pointers are stored in a linked list of pages. The list
44 * is initially empty, and pages are allocated on demand. The first
45 * function pointer in the first allocated page (the last one in
46 * the linked list) is reserved for the cleanup function.
47 *
48 * Outside the following functions, all pages are mprotect()'ed
49 * to prevent unintentional/malicious corruption.
50 */
51
52/*
53 * Register a function to be performed at exit or when a shared object
54 * with the given dso handle is unloaded dynamically. Also used as
55 * the backend for atexit(). For more info on this API, see:
56 *
57 * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
58 */
59int
60__cxa_atexit(void (*func)(void *), void *arg, void *dso)
61{
62 struct atexit *p = __atexit;
63 struct atexit_fn *fnp;
64 int pgsize = getpagesize();
65 int ret = -1;
66
67 if (pgsize < sizeof(*p))
68 return (-1);
69 _ATEXIT_LOCK();
70 p = __atexit;
71 if (p != NULL) {
72 if (p->ind + 1 >= p->max)
73 p = NULL;
74 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
75 goto unlock;
76 }
77 if (p == NULL) {
78 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
79 MAP_ANON | MAP_PRIVATE, -1, 0);
80 if (p == MAP_FAILED)
81 goto unlock;
82 if (__atexit == NULL) {
83 memset(&p->fns[0], 0, sizeof(p->fns[0]));
84 p->ind = 1;
85 } else
86 p->ind = 0;
87 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
88 sizeof(p->fns[0]);
89 p->next = __atexit;
90 __atexit = p;
91 }
92 fnp = &p->fns[p->ind++];
93 fnp->fn_ptr.cxa_func = func;
94 fnp->fn_arg = arg;
95 fnp->fn_dso = dso;
96 if (mprotect(p, pgsize, PROT_READ))
97 goto unlock;
98 ret = 0;
99unlock:
100 _ATEXIT_UNLOCK();
101 return (ret);
102}
103
104/*
105 * Call all handlers registered with __cxa_atexit() for the shared
106 * object owning 'dso'.
107 * Note: if 'dso' is NULL, then all remaining handlers are called.
108 */
109void
110__cxa_finalize(void *dso)
111{
112 struct atexit *p, *q;
113 struct atexit_fn fn;
114 int n, pgsize = getpagesize();
115 static int call_depth;
116
117 call_depth++;
118
119 for (p = __atexit; p != NULL; p = p->next) {
120 for (n = p->ind; --n >= 0;) {
121 if (p->fns[n].fn_ptr.cxa_func == NULL)
122 continue; /* already called */
123 if (dso != NULL && dso != p->fns[n].fn_dso)
124 continue; /* wrong DSO */
125
126 /*
127 * Mark handler as having been already called to avoid
128 * dupes and loops, then call the appropriate function.
129 */
130 fn = p->fns[n];
131 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
132 p->fns[n].fn_ptr.cxa_func = NULL;
133 mprotect(p, pgsize, PROT_READ);
134 }
135 if (fn.fn_dso != NULL)
136 (*fn.fn_ptr.cxa_func)(fn.fn_arg);
137 else
138 (*fn.fn_ptr.std_func)();
139 }
140 }
141
142 call_depth--;
143
144 /*
145 * If called via exit(), unmap the pages since we have now run
146 * all the handlers. We defer this until calldepth == 0 so that
147 * we don't unmap things prematurely if called recursively.
148 */
149 if (dso == NULL && call_depth == 0) {
150 for (p = __atexit; p != NULL; ) {
151 q = p;
152 p = p->next;
153 munmap(q, pgsize);
154 }
155 __atexit = NULL;
156 }
157}
158
159/*
160 * Register the cleanup function
161 */
162void
163__atexit_register_cleanup(void (*func)(void))
164{
165 struct atexit *p;
166 int pgsize = getpagesize();
167
168 if (pgsize < sizeof(*p))
169 return;
170 _ATEXIT_LOCK();
171 p = __atexit;
172 while (p != NULL && p->next != NULL)
173 p = p->next;
174 if (p == NULL) {
175 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
176 MAP_ANON | MAP_PRIVATE, -1, 0);
177 if (p == MAP_FAILED)
178 goto unlock;
179 p->ind = 1;
180 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
181 sizeof(p->fns[0]);
182 p->next = NULL;
183 __atexit = p;
184 } else {
185 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
186 goto unlock;
187 }
188 p->fns[0].fn_ptr.std_func = func;
189 p->fns[0].fn_arg = NULL;
190 p->fns[0].fn_dso = NULL;
191 mprotect(p, pgsize, PROT_READ);
192unlock:
193 _ATEXIT_UNLOCK();
194}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000000..c44005deda
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.h
@@ -0,0 +1,50 @@
1/* $OpenBSD: atexit.h,v 1.8 2013/06/02 21:08:36 matthew Exp $ */
2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
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 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
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.
30 *
31 */
32
33struct atexit {
34 struct atexit *next; /* next in list */
35 int ind; /* next index in this table */
36 int max; /* max entries >= ATEXIT_SIZE */
37 struct atexit_fn {
38 union {
39 void (*std_func)(void);
40 void (*cxa_func)(void *);
41 } fn_ptr;
42 void *fn_arg; /* argument for CXA callback */
43 void *fn_dso; /* shared module handle */
44 } fns[1]; /* the table itself */
45};
46
47extern struct atexit *__atexit; /* points to head of LIFO stack */
48
49int __cxa_atexit(void (*)(void *), void *, void *);
50void __cxa_finalize(void *);
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000000..53722a6253
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.3
@@ -0,0 +1,74 @@
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. 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.\" $OpenBSD: atof.3,v 1.7 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt ATOF 3
36.Os
37.Sh NAME
38.Nm atof
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft double
45.Fn atof "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atof
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtod(nptr, (char **)NULL);
58.Ed
59.Sh SEE ALSO
60.Xr atoi 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtoul 3
65.Sh STANDARDS
66The
67.Fn atof
68function conforms to
69.St -ansiC .
70.Sh HISTORY
71An
72.Fn atof
73function first appeared in
74.At v1 .
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
new file mode 100644
index 0000000000..d14b58b070
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atof.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33double
34atof(const char *ascii)
35{
36 return(strtod(ascii, (char **)NULL));
37}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000000..fd5c720e02
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.3
@@ -0,0 +1,91 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. 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. 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.\" $OpenBSD: atoi.3,v 1.11 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt ATOI 3
36.Os
37.Sh NAME
38.Nm atoi
39.Nd convert
40.Tn ASCII
41string to integer
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft int
45.Fn atoi "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoi
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57(int)strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtonum 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoi
69function conforms to
70.St -ansiC .
71.Sh HISTORY
72An
73.Fn atoi
74function first appeared in
75.At v1 .
76.Sh CAVEATS
77.Nm
78does no overflow checking, handles unsigned numbers poorly,
79and handles strings containing trailing extra characters
80(like
81.Dq "123abc" )
82poorly.
83Careful use of
84.Xr strtol 3
85and
86.Xr strtoul 3
87can alleviate these problems,
88but
89.Xr strtonum 3
90can be used to convert numbers from strings much more safely
91and easily.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000000..b0842678e2
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atoi.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33int
34atoi(const char *str)
35{
36 return((int)strtol(str, (char **)NULL, 10));
37}
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
new file mode 100644
index 0000000000..ae4cbc7c3d
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: atol.3,v 1.8 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt ATOL 3
36.Os
37.Sh NAME
38.Nm atol
39.Nd convert
40.Tn ASCII
41string to long integer
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft long
45.Fn atol "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atol
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atoll 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atol
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
new file mode 100644
index 0000000000..1970804401
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atol.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33long
34atol(const char *str)
35{
36 return(strtol(str, (char **)NULL, 10));
37}
diff --git a/src/lib/libc/stdlib/atoll.3 b/src/lib/libc/stdlib/atoll.3
new file mode 100644
index 0000000000..a9614ae7bb
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: atoll.3,v 1.6 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt ATOLL 3
36.Os
37.Sh NAME
38.Nm atoll
39.Nd convert
40.Tn ASCII
41string to long long integer
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft long long
45.Fn atoll "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoll
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtoll(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atol 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoll
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000000..a65e682cfb
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: atoll.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33long long
34atoll(str)
35 const char *str;
36{
37 return(strtoll(str, (char **)NULL, 10));
38}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
new file mode 100644
index 0000000000..270086df36
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -0,0 +1,84 @@
1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" The Regents of the University of California. 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. 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.\" $OpenBSD: bsearch.3,v 1.9 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt BSEARCH 3
36.Os
37.Sh NAME
38.Nm bsearch
39.Nd binary search of a sorted table
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft void *
43.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
44.Sh DESCRIPTION
45The
46.Fn bsearch
47function searches an array of
48.Fa nmemb
49objects, the initial member of which is
50pointed to by
51.Fa base ,
52for a member that matches the object pointed to by
53.Fa key .
54The size of each member of the array is specified by
55.Fa size .
56.Pp
57The contents of the array should be in ascending sorted order according
58to the comparison function referenced by
59.Fa compar .
60The
61.Fa compar
62routine is expected to have two arguments which point to the
63.Fa key
64object and to an array member, in that order, and should return an integer
65less than, equal to, or greater than zero if the
66.Fa key
67object is found, respectively, to be less than, to match, or be
68greater than the array member.
69.Sh RETURN VALUES
70The
71.Fn bsearch
72function returns a pointer to a matching member of the array, or a null
73pointer if no match is found.
74If two members compare as equal, which member is matched is unspecified.
75.Sh SEE ALSO
76.Xr db 3 ,
77.Xr lsearch 3 ,
78.Xr qsort 3 ,
79.Xr tsearch 3
80.Sh STANDARDS
81The
82.Fn bsearch
83function conforms to
84.St -ansiC .
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
new file mode 100644
index 0000000000..b48747236e
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,67 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <stdlib.h>
31
32/*
33 * Perform a binary search.
34 *
35 * The code below is a bit sneaky. After a comparison fails, we
36 * divide the work in half by moving either left or right. If lim
37 * is odd, moving left simply involves halving lim: e.g., when lim
38 * is 5 we look at item 2, so we change lim to 2 so that we will
39 * look at items 0 & 1. If lim is even, the same applies. If lim
40 * is odd, moving right again involves halving lim, this time moving
41 * the base up one item past p: e.g., when lim is 5 we change base
42 * to item 3 and make lim 2 so that we will look at items 3 and 4.
43 * If lim is even, however, we have to shrink it by one before
44 * halving: e.g., when lim is 4, we still looked at item 2, so we
45 * have to make lim 3, then halve, obtaining 1, so that we will only
46 * look at item 3.
47 */
48void *
49bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
50 int (*compar)(const void *, const void *))
51{
52 const char *base = base0;
53 int lim, cmp;
54 const void *p;
55
56 for (lim = nmemb; lim != 0; lim >>= 1) {
57 p = base + (lim >> 1) * size;
58 cmp = (*compar)(key, p);
59 if (cmp == 0)
60 return ((void *)p);
61 if (cmp > 0) { /* key > p: move right */
62 base = (char *)p + size;
63 lim--;
64 } /* else move left */
65 }
66 return (NULL);
67}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..acf6d1c8ac
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,39 @@
1/* $OpenBSD: cfree.c,v 1.6 2012/12/05 23:20:01 deraadt 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 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <stdlib.h>
29
30#ifdef __indr_reference
31__indr_reference(free, cfree);
32#else
33
34void
35cfree(void *p)
36{
37 free(p);
38}
39#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
new file mode 100644
index 0000000000..1a2a326269
--- /dev/null
+++ b/src/lib/libc/stdlib/div.3
@@ -0,0 +1,64 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek.
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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" $OpenBSD: div.3,v 1.11 2013/06/05 03:39:23 tedu Exp $
31.\"
32.Dd $Mdocdate: June 5 2013 $
33.Dt DIV 3
34.Os
35.Sh NAME
36.Nm div
37.Nd return quotient and remainder from division
38.Sh SYNOPSIS
39.In stdlib.h
40.Ft div_t
41.Fn div "int num" "int denom"
42.Sh DESCRIPTION
43The
44.Fn div
45function computes the value
46.Fa num Ns / Ns Fa denom
47and returns the quotient and remainder in a structure named
48.Fa div_t
49that contains two
50.Li int
51members named
52.Fa quot
53and
54.Fa rem .
55.Sh SEE ALSO
56.Xr imaxdiv 3 ,
57.Xr ldiv 3 ,
58.Xr lldiv 3 ,
59.Xr qdiv 3
60.Sh STANDARDS
61The
62.Fn div
63function conforms to
64.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
new file mode 100644
index 0000000000..f7ac2db4b0
--- /dev/null
+++ b/src/lib/libc/stdlib/div.c
@@ -0,0 +1,71 @@
1/* $OpenBSD: div.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <stdlib.h> /* div_t */
35
36div_t
37div(int num, int denom)
38{
39 div_t r;
40
41 r.quot = num / denom;
42 r.rem = num % denom;
43 /*
44 * The ANSI standard says that |r.quot| <= |n/d|, where
45 * n/d is to be computed in infinite precision. In other
46 * words, we should always truncate the quotient towards
47 * 0, never -infinity.
48 *
49 * Machine division and remainer may work either way when
50 * one or both of n or d is negative. If only one is
51 * negative and r.quot has been truncated towards -inf,
52 * r.rem will have the same sign as denom and the opposite
53 * sign of num; if both are negative and r.quot has been
54 * truncated towards -inf, r.rem will be positive (will
55 * have the opposite sign of num). These are considered
56 * `wrong'.
57 *
58 * If both are num and denom are positive, r will always
59 * be positive.
60 *
61 * This all boils down to:
62 * if num >= 0, but r.rem < 0, we got the wrong answer.
63 * In that case, to get the right answer, add 1 to r.quot and
64 * subtract denom from r.rem.
65 */
66 if (num >= 0 && r.rem < 0) {
67 r.quot++;
68 r.rem -= denom;
69 }
70 return (r);
71}
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
new file mode 100644
index 0000000000..b6c046c831
--- /dev/null
+++ b/src/lib/libc/stdlib/drand48.c
@@ -0,0 +1,23 @@
1/* $OpenBSD: drand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19double
20drand48(void)
21{
22 return erand48(__rand48_seed);
23}
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..d8a3489b1f
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,168 @@
1.\" $OpenBSD: ecvt.3,v 1.11 2013/06/05 03:39:23 tedu Exp $
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.\" Sponsored in part by the Defense Advanced Research Projects
18.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
19.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
20.\"
21.Dd $Mdocdate: June 5 2013 $
22.Dt ECVT 3
23.Os
24.Sh NAME
25.Nm ecvt ,
26.Nm fcvt ,
27.Nm gcvt
28.Nd convert double to
29.Tn ASCII
30string
31.Sh SYNOPSIS
32.In stdlib.h
33.Ft char *
34.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
35.Ft char *
36.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
37.Ft char *
38.Fn gcvt "double value" "int ndigit" "char *buf"
39.Sh DESCRIPTION
40.Bf -symbolic
41These functions are provided for compatibility with legacy code.
42New code should use the
43.Xr snprintf 3
44function for improved safety and portability.
45.Ef
46.Pp
47The
48.Fn ecvt ,
49.Fn fcvt
50and
51.Fn gcvt
52functions convert the double precision floating-point number
53.Fa value
54to a NUL-terminated
55.Tn ASCII
56string.
57.Pp
58The
59.Fn ecvt
60function converts
61.Fa value
62to a NUL-terminated string of exactly
63.Fa ndigit
64digits and returns a pointer to that string.
65The result is padded with zeroes from left to right as needed.
66There are no leading zeroes unless
67.Fa value
68itself is 0.
69The least significant digit is rounded in an implementation-dependent manner.
70The position of the decimal point relative to the beginning of the string
71is stored in
72.Fa decpt .
73A negative value indicates that the decimal point is located
74to the left of the returned digits (this occurs when there is no
75whole number component to
76.Fa value ) .
77If
78.Fa value
79is zero, it is unspecified whether the integer pointed to by
80.Fa decpt
81will be 0 or 1.
82The decimal point itself is not included in the returned string.
83If the sign of the result is negative, the integer pointed to by
84.Fa sign
85is non-zero; otherwise, it is 0.
86.Pp
87If the converted value is out of range or is not representable,
88the contents of the returned string are unspecified.
89.Pp
90The
91.Fn fcvt
92function is identical to
93.Fn ecvt
94with the exception that
95.Fa ndigit
96specifies the number of digits after the decimal point (zero-padded as
97needed).
98.Pp
99The
100.Fn gcvt
101function converts
102.Fa value
103to a NUL-terminated string similar to the %g
104.Xr printf 3
105format specifier and stores the result in
106.Fa buf .
107It produces
108.Fa ndigit
109significant digits similar to the %f
110.Xr printf 3
111format specifier where possible.
112If
113.Fa ndigit
114does allow sufficient precision, the result is stored in
115exponential notation similar to the %e
116.Xr printf 3
117format specifier.
118If
119.Fa value
120is less than zero,
121.Fa buf
122will be prefixed with a minus sign.
123A decimal point is included in the returned string if
124.Fa value
125is not a whole number.
126Unlike the
127.Fn ecvt
128and
129.Fn fcvt
130functions,
131.Fa buf
132is not zero-padded.
133.Sh RETURN VALUES
134The
135.Fn ecvt ,
136.Fn fcvt
137and
138.Fn gcvt
139functions return a NUL-terminated string representation of
140.Fa value .
141.Sh SEE ALSO
142.Xr printf 3 ,
143.Xr strtod 3
144.Sh STANDARDS
145The
146.Fn ecvt ,
147.Fn fcvt
148and
149.Fn gcvt
150functions conform to
151.St -p1003.1-2001 ;
152as of
153.St -p1003.1-2008
154they are no longer a part of the standard.
155.Sh CAVEATS
156The
157.Fn ecvt
158and
159.Fn fcvt
160functions return a pointer to internal storage space that will be
161overwritten by subsequent calls to either function.
162.Pp
163The maximum possible precision of the return value is limited by the
164precision of a double and may not be the same on all architectures.
165.Pp
166The
167.Xr snprintf 3
168function is preferred over these functions for new code.
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..4562e309e8
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: ecvt.c,v 1.8 2013/11/01 19:05:11 guenther Exp $ */
2
3/*
4 * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include "gdtoa.h"
27
28static char *__cvt(double, int, int *, int *, int, int);
29
30static char *
31__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
32{
33 static char *s;
34 char *p, *rve, c;
35 size_t siz;
36
37 if (ndigit == 0) {
38 *sign = value < 0.0;
39 *decpt = 0;
40 return ("");
41 }
42
43 if (s) {
44 free(s);
45 s = NULL;
46 }
47
48 if (ndigit < 0)
49 siz = -ndigit + 1;
50 else
51 siz = ndigit + 1;
52
53
54 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
55 if (value == 0.0) {
56 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
57 *sign = 0;
58 if ((rve = s = (char *)malloc(siz)) == NULL)
59 return(NULL);
60 *rve++ = '0';
61 *rve = '\0';
62 } else {
63 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
64 if (p == NULL)
65 return (NULL);
66 if (*decpt == 9999) {
67 /* Infinity or Nan, convert to inf or nan like printf */
68 *decpt = 0;
69 c = *p;
70 __freedtoa(p);
71 return(c == 'I' ? "inf" : "nan");
72 }
73 /* Make a local copy and adjust rve to be in terms of s */
74 if (pad && fmode)
75 siz += *decpt;
76 if ((s = (char *)malloc(siz)) == NULL) {
77 __freedtoa(p);
78 return(NULL);
79 }
80 (void) strlcpy(s, p, siz);
81 rve = s + (rve - p);
82 __freedtoa(p);
83 }
84
85 /* Add trailing zeros */
86 if (pad) {
87 siz -= rve - s;
88 while (--siz)
89 *rve++ = '0';
90 *rve = '\0';
91 }
92
93 return(s);
94}
95
96char *
97ecvt(double value, int ndigit, int *decpt, int *sign)
98{
99 return(__cvt(value, ndigit, decpt, sign, 0, 1));
100}
101
102char *
103fcvt(double value, int ndigit, int *decpt, int *sign)
104{
105 return(__cvt(value, ndigit, decpt, sign, 1, 1));
106}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
new file mode 100644
index 0000000000..2ffeaa6e71
--- /dev/null
+++ b/src/lib/libc/stdlib/erand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: erand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17double
18erand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ldexp((double) xseed[0], -48) +
22 ldexp((double) xseed[1], -32) +
23 ldexp((double) xseed[2], -16);
24}
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000000..26922ca7b8
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.3
@@ -0,0 +1,102 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: exit.3,v 1.15 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt EXIT 3
36.Os
37.Sh NAME
38.Nm exit
39.Nd perform normal program termination
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft void
43.Fn exit "int status"
44.Sh DESCRIPTION
45The
46.Fn exit
47function terminates a process.
48.Pp
49Before termination it performs the following functions in the
50order listed:
51.Bl -enum -offset indent
52.It
53Call the functions registered with the
54.Xr atexit 3
55function, in the reverse order of their registration.
56.It
57Flush all open output streams.
58.It
59Close all open streams.
60.It
61Unlink all files created with the
62.Xr tmpfile 3
63function.
64.El
65.Pp
66Following this,
67.Fn exit
68calls
69.Xr _exit 2 .
70Note that typically
71.Xr _exit 2
72only passes the lower 8 bits of
73.Fa status
74on to the parent, thus negative values have less meaning.
75.Sh RETURN VALUES
76The
77.Fn exit
78function never returns.
79.Sh SEE ALSO
80.Xr _exit 2 ,
81.Xr atexit 3 ,
82.Xr intro 3 ,
83.Xr sysexits 3 ,
84.Xr tmpfile 3
85.Sh STANDARDS
86The
87.Fn exit
88function conforms to
89.St -ansiC-99 .
90.Sh HISTORY
91An
92.Fn exit
93function first appeared as a system call in
94.At v1 .
95It has accepted the
96.Fa status
97argument since
98.At v2 .
99In
100.At v7 ,
101the bare system call was renamed to
102.Xr _exit 2 .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000000..83fe3d2de5
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: exit.c,v 1.12 2007/09/03 14:40:16 millert Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include "atexit.h"
36#include "thread_private.h"
37
38/*
39 * This variable is zero until a process has created a thread.
40 * It is used to avoid calling locking functions in libc when they
41 * are not required. By default, libc is intended to be(come)
42 * thread-safe, but without a (significant) penalty to non-threaded
43 * processes.
44 */
45int __isthreaded = 0;
46
47/*
48 * Exit, flushing stdio buffers if necessary.
49 */
50void
51exit(int status)
52{
53 /*
54 * Call functions registered by atexit() or _cxa_atexit()
55 * (including the stdio cleanup routine) and then _exit().
56 */
57 __cxa_finalize(NULL);
58 _exit(status);
59}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..f233332799
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,123 @@
1/* $OpenBSD: gcvt.c,v 1.13 2013/11/01 19:05:11 guenther Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003, 2006, 2010
5 * Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Sponsored in part by the Defense Advanced Research Projects
20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22 */
23
24#include <locale.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include "gdtoa.h"
29
30#define DEFPREC 6
31
32char *
33gcvt(double value, int ndigit, char *buf)
34{
35 char *digits, *dst, *src;
36 int i, decpt, sign;
37 struct lconv *lconv;
38
39 lconv = localeconv();
40 if (ndigit <= 0) {
41 /* Match printf(3) behavior. */
42 ndigit = ndigit ? DEFPREC : 1;
43 }
44
45 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
46 if (digits == NULL)
47 return (NULL);
48 if (decpt == 9999) {
49 /*
50 * Infinity or NaN, convert to inf or nan with sign.
51 * We can't infer buffer size based on ndigit.
52 * We have to assume it is at least 5 chars.
53 */
54 snprintf(buf, 5, "%s%s", sign ? "-" : "",
55 *digits == 'I' ? "inf" : "nan");
56 __freedtoa(digits);
57 return (buf);
58 }
59
60 dst = buf;
61 if (sign)
62 *dst++ = '-';
63
64 /* Match printf(3) behavior for exponential vs. regular fomatting. */
65 if (decpt <= -4 || decpt > ndigit) {
66 /* exponential format (e.g. 1.2345e+13) */
67 if (--decpt < 0) {
68 sign = 1;
69 decpt = -decpt;
70 } else
71 sign = 0;
72 src = digits;
73 *dst++ = *src++;
74 if (*src != '\0') {
75 *dst++ = *lconv->decimal_point;
76 do {
77 *dst++ = *src++;
78 } while (*src != '\0');
79 }
80 *dst++ = 'e';
81 if (sign)
82 *dst++ = '-';
83 else
84 *dst++ = '+';
85 if (decpt < 10) {
86 *dst++ = '0';
87 *dst++ = '0' + decpt;
88 *dst = '\0';
89 } else {
90 /* XXX - optimize */
91 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
92 continue;
93 dst[i + 1] = '\0';
94 while (decpt != 0) {
95 dst[i--] = '0' + decpt % 10;
96 decpt /= 10;
97 }
98 }
99 } else {
100 /* standard format */
101 for (i = 0, src = digits; i < decpt; i++) {
102 if (*src != '\0')
103 *dst++ = *src++;
104 else
105 *dst++ = '0';
106 }
107 if (*src != '\0') {
108 if (src == digits)
109 *dst++ = '0'; /* zero before decimal point */
110 *dst++ = *lconv->decimal_point;
111 while (decpt < 0) {
112 *dst++ = '0';
113 decpt++;
114 }
115 for (i = decpt; digits[i] != '\0'; i++) {
116 *dst++ = digits[i];
117 }
118 }
119 *dst = '\0';
120 }
121 __freedtoa(digits);
122 return (buf);
123}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000000..5239d1b0d5
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.3
@@ -0,0 +1,175 @@
1.\" Copyright (c) 1988, 1991, 1993
2.\" The Regents of the University of California. 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. 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.\" $OpenBSD: getenv.3,v 1.19 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt GETENV 3
36.Os
37.Sh NAME
38.Nm getenv ,
39.Nm putenv ,
40.Nm setenv ,
41.Nm unsetenv
42.Nd environment variable functions
43.Sh SYNOPSIS
44.In stdlib.h
45.Ft char *
46.Fn getenv "const char *name"
47.Ft int
48.Fn setenv "const char *name" "const char *value" "int overwrite"
49.Ft int
50.Fn putenv "char *string"
51.Ft int
52.Fn unsetenv "const char *name"
53.Sh DESCRIPTION
54These functions set, unset, and fetch environment variables from the host
55.Em environment list .
56.Pp
57The
58.Fn getenv
59function obtains the current value of the environment variable
60.Fa name .
61If the variable
62.Fa name
63is not in the current environment, a null pointer is returned.
64.Pp
65The
66.Fn setenv
67function inserts or resets the environment variable
68.Fa name
69in the current environment list.
70If the variable
71.Fa name
72does not exist in the list, it is inserted with the given
73.Fa value .
74If the variable does exist, the argument
75.Fa overwrite
76is tested; if
77.Fa overwrite
78is zero, the variable is not reset, otherwise it is reset to the given
79.Fa value .
80.Pp
81The
82.Fn putenv
83function takes an argument of the form
84.Ar name Ns = Ns Ar value .
85The memory pointed to by
86.Ar string
87becomes part of the environment and must not be deallocated by the caller.
88If the variable already exists, it will be overwritten.
89A common source of bugs is to pass a
90.Ar string
91argument that is a locally scoped string buffer.
92This will result in corruption of the environment after leaving
93the scope in which the variable is defined.
94For this reason, the
95.Fn setenv
96function is preferred over
97.Fn putenv .
98.Pp
99The
100.Fn unsetenv
101function deletes all instances of the variable name pointed to by
102.Fa name
103from the list.
104.Sh RETURN VALUES
105These functions
106return zero if successful; otherwise the global variable
107.Va errno
108is set to indicate the error and \-1 is returned.
109.Pp
110If
111.Fn getenv
112is successful, the string returned should be considered read-only.
113.Sh ERRORS
114.Bl -tag -width Er
115.It Bq Er EINVAL
116The
117.Fn setenv
118or
119.Fn unsetenv
120function was passed an empty
121.Ar name
122or a NULL pointer, or was passed a
123.Ar name
124containing an
125.Sq =
126character.
127.Pp
128The
129.Fn putenv
130function was passed a
131.Ar string
132that did not contain an
133.Sq =
134character.
135.It Bq Er ENOMEM
136The
137.Fn setenv
138or
139.Fn putenv
140function failed because it was unable to allocate memory for the environment.
141.El
142.Sh SEE ALSO
143.Xr csh 1 ,
144.Xr sh 1 ,
145.Xr execve 2 ,
146.Xr environ 7
147.Sh STANDARDS
148The
149.Fn getenv
150function conforms to
151.St -ansiC .
152The
153.Fn putenv ,
154.Fn setenv ,
155and
156.Fn unsetenv
157functions conform to
158.St -p1003.1-2008 .
159.Sh HISTORY
160The function
161.Fn getenv
162appeared in
163.At v7
164and
165.Bx 3 .
166The functions
167.Fn setenv
168and
169.Fn unsetenv
170appeared in
171.Bx 4.3 Tahoe .
172The
173.Fn putenv
174function appeared in
175.Bx 4.3 Reno .
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
new file mode 100644
index 0000000000..fd8482e9e3
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.c
@@ -0,0 +1,81 @@
1/* $OpenBSD: getenv.c,v 1.10 2010/08/23 22:31:50 millert Exp $ */
2/*
3 * Copyright (c) 1987, 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. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32#include <string.h>
33
34char *__findenv(const char *name, int len, int *offset);
35
36/*
37 * __findenv --
38 * Returns pointer to value associated with name, if any, else NULL.
39 * Starts searching within the environmental array at offset.
40 * Sets offset to be the offset of the name/value combination in the
41 * environmental array, for use by putenv(3), setenv(3) and unsetenv(3).
42 * Explicitly removes '=' in argument name.
43 *
44 * This routine *should* be a static; don't use it.
45 */
46char *
47__findenv(const char *name, int len, int *offset)
48{
49 extern char **environ;
50 int i;
51 const char *np;
52 char **p, *cp;
53
54 if (name == NULL || environ == NULL)
55 return (NULL);
56 for (p = environ + *offset; (cp = *p) != NULL; ++p) {
57 for (np = name, i = len; i && *cp; i--)
58 if (*cp++ != *np++)
59 break;
60 if (i == 0 && *cp++ == '=') {
61 *offset = p - environ;
62 return (cp);
63 }
64 }
65 return (NULL);
66}
67
68/*
69 * getenv --
70 * Returns ptr to value associated with name, if any, else NULL.
71 */
72char *
73getenv(const char *name)
74{
75 int offset = 0;
76 const char *np;
77
78 for (np = name; *np && *np != '='; ++np)
79 ;
80 return (__findenv(name, (int)(np - name), &offset));
81}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000000..6661e03841
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,364 @@
1.\" Copyright (c) 1988, 1991, 1993
2.\" The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: getopt.3,v 1.44 2014/01/21 03:15:45 schwarze Exp $
29.\"
30.Dd $Mdocdate: January 21 2014 $
31.Dt GETOPT 3
32.Os
33.Sh NAME
34.Nm getopt
35.Nd get option character from command line argument list
36.Sh SYNOPSIS
37.In unistd.h
38.Vt extern char *optarg;
39.Vt extern int opterr;
40.Vt extern int optind;
41.Vt extern int optopt;
42.Vt extern int optreset;
43.Ft int
44.Fn getopt "int argc" "char * const *argv" "const char *optstring"
45.Sh DESCRIPTION
46The
47.Fn getopt
48function incrementally parses a command line argument list
49.Fa argv
50and returns the next
51.Em known
52option character.
53An option character is
54.Em known
55if it has been specified in the string of accepted option characters,
56.Fa optstring .
57.Pp
58The option string
59.Fa optstring
60may contain the following elements: individual characters,
61characters followed by a colon, and characters followed by two colons.
62A character followed by a single colon indicates that an argument
63is to follow the option on the command line.
64Two colons indicates that the argument is optional \- this is an
65extension not covered by POSIX.
66For example, an option string
67.Qq x
68recognizes an option
69.Fl x ,
70and an option string
71.Qq Li x:
72recognizes an option and argument
73.Fl x Ar argument .
74It does not matter to
75.Fn getopt
76if a following argument has leading whitespace; except in the case where
77the argument is optional, denoted with two colons, no leading whitespace
78is permitted.
79.Pp
80On return from
81.Fn getopt ,
82.Va optarg
83points to an option argument, if it is anticipated,
84and the variable
85.Va optind
86contains the index to the next
87.Fa argv
88argument for a subsequent call
89to
90.Fn getopt .
91.Pp
92The variables
93.Va opterr
94and
95.Va optind
96are both initialized to 1.
97The
98.Va optind
99variable may be set to another value larger than 0 before a set of calls to
100.Fn getopt
101in order to skip over more or less
102.Fa argv
103entries.
104An
105.Va optind
106value of 0 is reserved for compatibility with GNU
107.Fn getopt .
108.Pp
109In order to use
110.Fn getopt
111to evaluate multiple sets of arguments, or to evaluate a single set of
112arguments multiple times,
113the variable
114.Va optreset
115must be set to 1 before the second and each additional set of calls to
116.Fn getopt ,
117and the variable
118.Va optind
119must be reinitialized.
120.Pp
121The
122.Fn getopt
123function returns \-1 when the argument list is exhausted.
124The interpretation of options in the argument list may be cancelled
125by the option
126.Ql --
127(double dash) which causes
128.Fn getopt
129to signal the end of argument processing and return \-1.
130When all options have been processed (i.e., up to the first non-option
131argument),
132.Fn getopt
133returns \-1.
134.Sh RETURN VALUES
135The
136.Fn getopt
137function returns the next known option character in
138.Fa optstring .
139If
140.Fn getopt
141encounters a character not found in
142.Fa optstring
143or if it detects a missing option argument,
144it returns
145.Sq \&?
146(question mark).
147If
148.Fa optstring
149has a leading
150.Sq \&:
151then a missing option argument causes
152.Sq \&:
153to be returned instead of
154.Sq \&? .
155In either case, the variable
156.Va optopt
157is set to the character that caused the error.
158The
159.Fn getopt
160function returns \-1 when the argument list is exhausted.
161.Sh EXAMPLES
162The following code accepts the options
163.Fl b
164and
165.Fl f Ar argument
166and adjusts
167.Va argc
168and
169.Va argv
170after option argument processing has completed.
171.Bd -literal -offset indent
172int bflag, ch, fd;
173
174bflag = 0;
175while ((ch = getopt(argc, argv, "bf:")) != -1) {
176 switch (ch) {
177 case 'b':
178 bflag = 1;
179 break;
180 case 'f':
181 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
182 err(1, "%s", optarg);
183 break;
184 default:
185 usage();
186 /* NOTREACHED */
187 }
188}
189argc -= optind;
190argv += optind;
191.Ed
192.Sh DIAGNOSTICS
193If the
194.Fn getopt
195function encounters a character not found in the string
196.Fa optstring
197or detects
198a missing option argument, it writes an error message to
199.Em stderr
200and returns
201.Ql \&? .
202Setting
203.Va opterr
204to a zero will disable these error messages.
205If
206.Fa optstring
207has a leading
208.Ql \&:
209then a missing option argument causes a
210.Ql \&:
211to be returned in addition to suppressing any error messages.
212.Pp
213Option arguments are allowed to begin with
214.Ql - ;
215this is reasonable but reduces the amount of error checking possible.
216.Sh SEE ALSO
217.Xr getopt 1 ,
218.Xr getopt_long 3 ,
219.Xr getsubopt 3
220.Sh STANDARDS
221The
222.Fn getopt
223function implements a superset of the functionality specified by
224.St -p1003.1 .
225.Pp
226The following extensions are supported:
227.Bl -tag -width "xxx"
228.It Li o
229The
230.Va optreset
231variable was added to make it possible to call the
232.Fn getopt
233function multiple times.
234.It Li o
235If the
236.Va optind
237variable is set to 0,
238.Fn getopt
239will behave as if the
240.Va optreset
241variable has been set.
242This is for compatibility with
243.Tn GNU
244.Fn getopt .
245New code should use
246.Va optreset
247instead.
248.It Li o
249If the first character of
250.Fa optstring
251is a plus sign
252.Pq Ql + ,
253it will be ignored.
254This is for compatibility with
255.Tn GNU
256.Fn getopt .
257.It Li o
258If the first character of
259.Fa optstring
260is a dash
261.Pq Ql - ,
262non-options will be returned as arguments to the option character
263.Ql \e1 .
264This is for compatibility with
265.Tn GNU
266.Fn getopt .
267.It Li o
268A single dash
269.Pq Ql -
270may be specified as a character in
271.Fa optstring ,
272however it should
273.Em never
274have an argument associated with it.
275This allows
276.Fn getopt
277to be used with programs that expect
278.Ql -
279as an option flag.
280This practice is wrong, and should not be used in any current development.
281It is provided for backward compatibility
282.Em only .
283Care should be taken not to use
284.Ql -
285as the first character in
286.Fa optstring
287to avoid a semantic conflict with
288.Tn GNU
289.Fn getopt
290semantics (see above).
291By default, a single dash causes
292.Fn getopt
293to return \-1.
294.El
295.Pp
296Historic
297.Bx
298versions of
299.Fn getopt
300set
301.Fa optopt
302to the last option character processed.
303However, this conflicts with
304.St -p1003.1
305which stipulates that
306.Fa optopt
307be set to the last character that caused an error.
308.Sh HISTORY
309The
310.Fn getopt
311function appeared in
312.Bx 4.3 .
313.Sh BUGS
314The
315.Fn getopt
316function was once specified to return
317.Dv EOF
318instead of \-1.
319This was changed by
320.St -p1003.2-92
321to decouple
322.Fn getopt
323from
324.In stdio.h .
325.Pp
326It is possible to handle digits as option letters.
327This allows
328.Fn getopt
329to be used with programs that expect a number
330.Pq Dq Li \-3
331as an option.
332This practice is wrong, and should not be used in any current development.
333It is provided for backward compatibility
334.Em only .
335The following code fragment works in most cases and can handle mixed
336number and letter arguments.
337.Bd -literal -offset indent
338int aflag = 0, bflag = 0, ch, lastch = '\e0';
339int length = -1, newarg = 1, prevoptind = 1;
340
341while ((ch = getopt(argc, argv, "0123456789ab")) != -1) {
342 switch (ch) {
343 case '0': case '1': case '2': case '3': case '4':
344 case '5': case '6': case '7': case '8': case '9':
345 if (newarg || !isdigit(lastch))
346 length = 0;
347 else if (length > INT_MAX / 10)
348 usage();
349 length = (length * 10) + (ch - '0');
350 break;
351 case 'a':
352 aflag = 1;
353 break;
354 case 'b':
355 bflag = 1;
356 break;
357 default:
358 usage();
359 }
360 lastch = ch;
361 newarg = optind != prevoptind;
362 prevoptind = optind;
363}
364.Ed
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..a5973d6c99
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,445 @@
1.\" $OpenBSD: getopt_long.3,v 1.20 2013/06/05 03:39:23 tedu Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
32.\"
33.Dd $Mdocdate: June 5 2013 $
34.Dt GETOPT_LONG 3
35.Os
36.Sh NAME
37.Nm getopt_long ,
38.Nm getopt_long_only
39.Nd get long options from command line argument list
40.Sh SYNOPSIS
41.In getopt.h
42.Vt extern char *optarg;
43.Vt extern int optind;
44.Vt extern int optopt;
45.Vt extern int opterr;
46.Vt extern int optreset;
47.Ft int
48.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
49.Ft int
50.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
51.Sh DESCRIPTION
52The
53.Fn getopt_long
54function is similar to
55.Xr getopt 3
56but it accepts options in two forms: words and characters.
57The
58.Fn getopt_long
59function provides a superset of the functionality of
60.Xr getopt 3 .
61.Fn getopt_long
62can be used in two ways.
63In the first way, every long option understood by the program has a
64corresponding short option, and the option structure is only used to
65translate from long options to short options.
66When used in this fashion,
67.Fn getopt_long
68behaves identically to
69.Xr getopt 3 .
70This is a good way to add long option processing to an existing program
71with the minimum of rewriting.
72.Pp
73In the second mechanism, a long option sets a flag in the
74.Fa option
75structure passed, or will store a pointer to the command line argument
76in the
77.Fa option
78structure passed to it for options that take arguments.
79Additionally, the long option's argument may be specified as a single
80argument with an equal sign, e.g.
81.Bd -literal -offset indent
82$ myprogram --myoption=somevalue
83.Ed
84.Pp
85When a long option is processed, the call to
86.Fn getopt_long
87will return 0.
88For this reason, long option processing without
89shortcuts is not backwards compatible with
90.Xr getopt 3 .
91.Pp
92It is possible to combine these methods, providing for long options
93processing with short option equivalents for some options.
94Less frequently used options would be processed as long options only.
95.Pp
96Abbreviated long option names are accepted when
97.Fn getopt_long
98processes long options if the abbreviation is unique.
99An exact match is always preferred for a defined long option.
100.Pp
101The
102.Fn getopt_long
103call requires an array to be initialized describing the long
104options.
105Each element of the array is a structure:
106.Bd -literal -offset indent
107struct option {
108 char *name;
109 int has_arg;
110 int *flag;
111 int val;
112};
113.Ed
114.Pp
115The
116.Fa name
117field should contain the option name without the leading double dash.
118.Pp
119The
120.Fa has_arg
121field should be one of:
122.Pp
123.Bl -tag -width "optional_argument" -compact -offset indent
124.It Dv no_argument
125no argument to the option is expected.
126.It Dv required_argument
127an argument to the option is required.
128.It Dv optional_argument
129an argument to the option may be presented.
130.El
131.Pp
132If
133.Fa flag
134is not
135.Dv NULL ,
136then the integer pointed to by it will be set to the value in the
137.Fa val
138field.
139If the
140.Fa flag
141field is
142.Dv NULL ,
143then the
144.Fa val
145field will be returned.
146Setting
147.Fa flag
148to
149.Dv NULL
150and setting
151.Fa val
152to the corresponding short option will make this function act just
153like
154.Xr getopt 3 .
155.Pp
156If the
157.Fa longindex
158field is not
159.Dv NULL ,
160then the integer pointed to by it will be set to the index of the long
161option relative to
162.Fa longopts .
163.Pp
164The last element of the
165.Fa longopts
166array has to be filled with zeroes.
167.Pp
168The
169.Fn getopt_long_only
170function behaves identically to
171.Fn getopt_long
172with the exception that long options may start with
173.Sq -
174in addition to
175.Sq -- .
176If an option starting with
177.Sq -
178does not match a long option but does match a single-character option,
179the single-character option is returned.
180.Sh RETURN VALUES
181If the
182.Fa flag
183field in
184.Li struct option
185is
186.Dv NULL ,
187.Fn getopt_long
188and
189.Fn getopt_long_only
190return the value specified in the
191.Fa val
192field, which is usually just the corresponding short option.
193If
194.Fa flag
195is not
196.Dv NULL ,
197these functions return 0 and store
198.Fa val
199in the location pointed to by
200.Fa flag .
201These functions return
202.Sq \&:
203if there was a missing option argument,
204.Sq \&?
205if the user specified an unknown or ambiguous option, and
206\-1 when the argument list has been exhausted.
207.Sh IMPLEMENTATION DIFFERENCES
208This section describes differences to the GNU implementation
209found in glibc-2.1.3:
210.Bl -bullet
211.It
212handling of
213.Ql -
214within the option string (not the first character):
215.Bl -tag -width "OpenBSD"
216.It GNU
217treats a
218.Ql -
219on the command line as a non-argument.
220.It OpenBSD
221a
222.Ql -
223within the option string matches a
224.Ql -
225(single dash) on the command line.
226This functionality is provided for backward compatibility with
227programs, such as
228.Xr su 1 ,
229that use
230.Ql -
231as an option flag.
232This practice is wrong, and should not be used in any current development.
233.El
234.It
235handling of
236.Ql ::
237in the option string in the presence of
238.Ev POSIXLY_CORRECT :
239.Bl -tag -width "OpenBSD"
240.It Both
241GNU and
242.Ox
243ignore
244.Ev POSIXLY_CORRECT
245here and take
246.Ql ::
247to mean the preceding option takes an optional argument.
248.El
249.It
250return value in case of missing argument if first character
251(after
252.Ql +
253or
254.Ql - )
255in the option string is not
256.Ql \&: :
257.Bl -tag -width "OpenBSD"
258.It GNU
259returns
260.Ql \&?
261.It OpenBSD
262returns
263.Ql \&:
264(since
265.Ox Ns 's
266.Xr getopt 3
267does).
268.El
269.It
270handling of
271.Ql --a
272in
273.Xr getopt 3 :
274.Bl -tag -width "OpenBSD"
275.It GNU
276parses this as option
277.Ql - ,
278option
279.Ql a .
280.It OpenBSD
281parses this as
282.Ql -- ,
283and returns \-1 (ignoring the
284.Ql a )
285(because the original
286.Fn getopt
287did.)
288.El
289.It
290setting of
291.Va optopt
292for long options with
293.Va flag
294.No non- Ns Dv NULL :
295.Bl -tag -width "OpenBSD"
296.It GNU
297sets
298.Va optopt
299to
300.Va val .
301.It OpenBSD
302sets
303.Va optopt
304to 0 (since
305.Va val
306would never be returned).
307.El
308.It
309handling of
310.Ql -W
311with
312.Ql W;
313in the option string in
314.Xr getopt 3
315(not
316.Fn getopt_long ) :
317.Bl -tag -width "OpenBSD"
318.It GNU
319causes a segmentation fault.
320.It OpenBSD
321no special handling is done;
322.Ql W;
323is interpreted as two separate options, neither of which take an argument.
324.El
325.It
326setting of
327.Va optarg
328for long options without an argument that are invoked via
329.Ql -W
330(with
331.Ql W;
332in the option string):
333.Bl -tag -width "OpenBSD"
334.It GNU
335sets
336.Va optarg
337to the option name (the argument of
338.Ql -W ) .
339.It OpenBSD
340sets
341.Va optarg
342to
343.Dv NULL
344(the argument of the long option).
345.El
346.It
347handling of
348.Ql -W
349with an argument that is not (a prefix to) a known long option
350(with
351.Ql W;
352in the option string):
353.Bl -tag -width "OpenBSD"
354.It GNU
355returns
356.Ql -W
357with
358.Va optarg
359set to the unknown option.
360.It OpenBSD
361treats this as an error (unknown option) and returns
362.Ql \&?
363with
364.Va optopt
365set to 0 and
366.Va optarg
367set to
368.Dv NULL
369(as GNU's man page documents).
370.El
371.It
372The error messages are different.
373.It
374.Ox
375does not permute the argument vector at the same points in
376the calling sequence as GNU does.
377The aspects normally used by the caller
378(ordering after \-1 is returned, value of
379.Va optind
380relative to current positions) are the same, though.
381(We do fewer variable swaps.)
382.El
383.Sh ENVIRONMENT
384.Bl -tag -width Ev
385.It Ev POSIXLY_CORRECT
386If set, option processing stops when the first non-option is found and
387a leading
388.Sq +
389in the
390.Ar optstring
391is ignored.
392.El
393.Sh EXAMPLES
394.Bd -literal
395int bflag, ch, fd;
396int daggerset;
397
398/* options descriptor */
399static struct option longopts[] = {
400 { "buffy", no_argument, NULL, 'b' },
401 { "fluoride", required_argument, NULL, 'f' },
402 { "daggerset", no_argument, &daggerset, 1 },
403 { NULL, 0, NULL, 0 }
404};
405
406bflag = 0;
407while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
408 switch (ch) {
409 case 'b':
410 bflag = 1;
411 break;
412 case 'f':
413 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
414 err(1, "unable to open %s", optarg);
415 break;
416 case 0:
417 if (daggerset)
418 fprintf(stderr, "Buffy will use her dagger to "
419 "apply fluoride to dracula's teeth\en");
420 break;
421 default:
422 usage();
423 /* NOTREACHED */
424 }
425argc -= optind;
426argv += optind;
427.Ed
428.Sh SEE ALSO
429.Xr getopt 3
430.Sh HISTORY
431The
432.Fn getopt_long
433and
434.Fn getopt_long_only
435functions first appeared in GNU libiberty.
436This implementation first appeared in
437.Ox 3.3 .
438.Sh BUGS
439The
440.Ar argv
441argument is not really
442.Dv const
443as its elements may be permuted (unless
444.Ev POSIXLY_CORRECT
445is set).
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..f46cd8bf4e
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,518 @@
1/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3
4/*
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Sponsored in part by the Defense Advanced Research Projects
20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22 */
23/*-
24 * Copyright (c) 2000 The NetBSD Foundation, Inc.
25 * All rights reserved.
26 *
27 * This code is derived from software contributed to The NetBSD Foundation
28 * by Dieter Baron and Thomas Klausner.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
40 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
43 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 * POSSIBILITY OF SUCH DAMAGE.
50 */
51
52#include <err.h>
53#include <errno.h>
54#include <getopt.h>
55#include <stdlib.h>
56#include <string.h>
57
58int opterr = 1; /* if error message should be printed */
59int optind = 1; /* index into parent argv vector */
60int optopt = '?'; /* character checked for validity */
61int optreset; /* reset getopt */
62char *optarg; /* argument associated with option */
63
64#define PRINT_ERROR ((opterr) && (*options != ':'))
65
66#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
67#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
68#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
69
70/* return values */
71#define BADCH (int)'?'
72#define BADARG ((*options == ':') ? (int)':' : (int)'?')
73#define INORDER (int)1
74
75#define EMSG ""
76
77static int getopt_internal(int, char * const *, const char *,
78 const struct option *, int *, int);
79static int parse_long_options(char * const *, const char *,
80 const struct option *, int *, int, int);
81static int gcd(int, int);
82static void permute_args(int, int, int, char * const *);
83
84static char *place = EMSG; /* option letter processing */
85
86/* XXX: set optreset to 1 rather than these two */
87static int nonopt_start = -1; /* first non option argument (for permute) */
88static int nonopt_end = -1; /* first option after non options (for permute) */
89
90/* Error messages */
91static const char recargchar[] = "option requires an argument -- %c";
92static const char recargstring[] = "option requires an argument -- %s";
93static const char ambig[] = "ambiguous option -- %.*s";
94static const char noarg[] = "option doesn't take an argument -- %.*s";
95static const char illoptchar[] = "unknown option -- %c";
96static const char illoptstring[] = "unknown option -- %s";
97
98/*
99 * Compute the greatest common divisor of a and b.
100 */
101static int
102gcd(int a, int b)
103{
104 int c;
105
106 c = a % b;
107 while (c != 0) {
108 a = b;
109 b = c;
110 c = a % b;
111 }
112
113 return (b);
114}
115
116/*
117 * Exchange the block from nonopt_start to nonopt_end with the block
118 * from nonopt_end to opt_end (keeping the same order of arguments
119 * in each block).
120 */
121static void
122permute_args(int panonopt_start, int panonopt_end, int opt_end,
123 char * const *nargv)
124{
125 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
126 char *swap;
127
128 /*
129 * compute lengths of blocks and number and size of cycles
130 */
131 nnonopts = panonopt_end - panonopt_start;
132 nopts = opt_end - panonopt_end;
133 ncycle = gcd(nnonopts, nopts);
134 cyclelen = (opt_end - panonopt_start) / ncycle;
135
136 for (i = 0; i < ncycle; i++) {
137 cstart = panonopt_end+i;
138 pos = cstart;
139 for (j = 0; j < cyclelen; j++) {
140 if (pos >= panonopt_end)
141 pos -= nnonopts;
142 else
143 pos += nopts;
144 swap = nargv[pos];
145 /* LINTED const cast */
146 ((char **) nargv)[pos] = nargv[cstart];
147 /* LINTED const cast */
148 ((char **)nargv)[cstart] = swap;
149 }
150 }
151}
152
153/*
154 * parse_long_options --
155 * Parse long options in argc/argv argument vector.
156 * Returns -1 if short_too is set and the option does not match long_options.
157 */
158static int
159parse_long_options(char * const *nargv, const char *options,
160 const struct option *long_options, int *idx, int short_too, int flags)
161{
162 char *current_argv, *has_equal;
163 size_t current_argv_len;
164 int i, match, exact_match, second_partial_match;
165
166 current_argv = place;
167 match = -1;
168 exact_match = 0;
169 second_partial_match = 0;
170
171 optind++;
172
173 if ((has_equal = strchr(current_argv, '=')) != NULL) {
174 /* argument found (--option=arg) */
175 current_argv_len = has_equal - current_argv;
176 has_equal++;
177 } else
178 current_argv_len = strlen(current_argv);
179
180 for (i = 0; long_options[i].name; i++) {
181 /* find matching long option */
182 if (strncmp(current_argv, long_options[i].name,
183 current_argv_len))
184 continue;
185
186 if (strlen(long_options[i].name) == current_argv_len) {
187 /* exact match */
188 match = i;
189 exact_match = 1;
190 break;
191 }
192 /*
193 * If this is a known short option, don't allow
194 * a partial match of a single character.
195 */
196 if (short_too && current_argv_len == 1)
197 continue;
198
199 if (match == -1) /* first partial match */
200 match = i;
201 else if ((flags & FLAG_LONGONLY) ||
202 long_options[i].has_arg != long_options[match].has_arg ||
203 long_options[i].flag != long_options[match].flag ||
204 long_options[i].val != long_options[match].val)
205 second_partial_match = 1;
206 }
207 if (!exact_match && second_partial_match) {
208 /* ambiguous abbreviation */
209 if (PRINT_ERROR)
210 warnx(ambig, (int)current_argv_len, current_argv);
211 optopt = 0;
212 return (BADCH);
213 }
214 if (match != -1) { /* option found */
215 if (long_options[match].has_arg == no_argument
216 && has_equal) {
217 if (PRINT_ERROR)
218 warnx(noarg, (int)current_argv_len,
219 current_argv);
220 /*
221 * XXX: GNU sets optopt to val regardless of flag
222 */
223 if (long_options[match].flag == NULL)
224 optopt = long_options[match].val;
225 else
226 optopt = 0;
227 return (BADARG);
228 }
229 if (long_options[match].has_arg == required_argument ||
230 long_options[match].has_arg == optional_argument) {
231 if (has_equal)
232 optarg = has_equal;
233 else if (long_options[match].has_arg ==
234 required_argument) {
235 /*
236 * optional argument doesn't use next nargv
237 */
238 optarg = nargv[optind++];
239 }
240 }
241 if ((long_options[match].has_arg == required_argument)
242 && (optarg == NULL)) {
243 /*
244 * Missing argument; leading ':' indicates no error
245 * should be generated.
246 */
247 if (PRINT_ERROR)
248 warnx(recargstring,
249 current_argv);
250 /*
251 * XXX: GNU sets optopt to val regardless of flag
252 */
253 if (long_options[match].flag == NULL)
254 optopt = long_options[match].val;
255 else
256 optopt = 0;
257 --optind;
258 return (BADARG);
259 }
260 } else { /* unknown option */
261 if (short_too) {
262 --optind;
263 return (-1);
264 }
265 if (PRINT_ERROR)
266 warnx(illoptstring, current_argv);
267 optopt = 0;
268 return (BADCH);
269 }
270 if (idx)
271 *idx = match;
272 if (long_options[match].flag) {
273 *long_options[match].flag = long_options[match].val;
274 return (0);
275 } else
276 return (long_options[match].val);
277}
278
279/*
280 * getopt_internal --
281 * Parse argc/argv argument vector. Called by user level routines.
282 */
283static int
284getopt_internal(int nargc, char * const *nargv, const char *options,
285 const struct option *long_options, int *idx, int flags)
286{
287 char *oli; /* option letter list index */
288 int optchar, short_too;
289 static int posixly_correct = -1;
290
291 if (options == NULL)
292 return (-1);
293
294 /*
295 * XXX Some GNU programs (like cvs) set optind to 0 instead of
296 * XXX using optreset. Work around this braindamage.
297 */
298 if (optind == 0)
299 optind = optreset = 1;
300
301 /*
302 * Disable GNU extensions if POSIXLY_CORRECT is set or options
303 * string begins with a '+'.
304 */
305 if (posixly_correct == -1 || optreset)
306 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
307 if (*options == '-')
308 flags |= FLAG_ALLARGS;
309 else if (posixly_correct || *options == '+')
310 flags &= ~FLAG_PERMUTE;
311 if (*options == '+' || *options == '-')
312 options++;
313
314 optarg = NULL;
315 if (optreset)
316 nonopt_start = nonopt_end = -1;
317start:
318 if (optreset || !*place) { /* update scanning pointer */
319 optreset = 0;
320 if (optind >= nargc) { /* end of argument vector */
321 place = EMSG;
322 if (nonopt_end != -1) {
323 /* do permutation, if we have to */
324 permute_args(nonopt_start, nonopt_end,
325 optind, nargv);
326 optind -= nonopt_end - nonopt_start;
327 }
328 else if (nonopt_start != -1) {
329 /*
330 * If we skipped non-options, set optind
331 * to the first of them.
332 */
333 optind = nonopt_start;
334 }
335 nonopt_start = nonopt_end = -1;
336 return (-1);
337 }
338 if (*(place = nargv[optind]) != '-' ||
339 (place[1] == '\0' && strchr(options, '-') == NULL)) {
340 place = EMSG; /* found non-option */
341 if (flags & FLAG_ALLARGS) {
342 /*
343 * GNU extension:
344 * return non-option as argument to option 1
345 */
346 optarg = nargv[optind++];
347 return (INORDER);
348 }
349 if (!(flags & FLAG_PERMUTE)) {
350 /*
351 * If no permutation wanted, stop parsing
352 * at first non-option.
353 */
354 return (-1);
355 }
356 /* do permutation */
357 if (nonopt_start == -1)
358 nonopt_start = optind;
359 else if (nonopt_end != -1) {
360 permute_args(nonopt_start, nonopt_end,
361 optind, nargv);
362 nonopt_start = optind -
363 (nonopt_end - nonopt_start);
364 nonopt_end = -1;
365 }
366 optind++;
367 /* process next argument */
368 goto start;
369 }
370 if (nonopt_start != -1 && nonopt_end == -1)
371 nonopt_end = optind;
372
373 /*
374 * If we have "-" do nothing, if "--" we are done.
375 */
376 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
377 optind++;
378 place = EMSG;
379 /*
380 * We found an option (--), so if we skipped
381 * non-options, we have to permute.
382 */
383 if (nonopt_end != -1) {
384 permute_args(nonopt_start, nonopt_end,
385 optind, nargv);
386 optind -= nonopt_end - nonopt_start;
387 }
388 nonopt_start = nonopt_end = -1;
389 return (-1);
390 }
391 }
392
393 /*
394 * Check long options if:
395 * 1) we were passed some
396 * 2) the arg is not just "-"
397 * 3) either the arg starts with -- we are getopt_long_only()
398 */
399 if (long_options != NULL && place != nargv[optind] &&
400 (*place == '-' || (flags & FLAG_LONGONLY))) {
401 short_too = 0;
402 if (*place == '-')
403 place++; /* --foo long option */
404 else if (*place != ':' && strchr(options, *place) != NULL)
405 short_too = 1; /* could be short option too */
406
407 optchar = parse_long_options(nargv, options, long_options,
408 idx, short_too, flags);
409 if (optchar != -1) {
410 place = EMSG;
411 return (optchar);
412 }
413 }
414
415 if ((optchar = (int)*place++) == (int)':' ||
416 (optchar == (int)'-' && *place != '\0') ||
417 (oli = strchr(options, optchar)) == NULL) {
418 /*
419 * If the user specified "-" and '-' isn't listed in
420 * options, return -1 (non-option) as per POSIX.
421 * Otherwise, it is an unknown option character (or ':').
422 */
423 if (optchar == (int)'-' && *place == '\0')
424 return (-1);
425 if (!*place)
426 ++optind;
427 if (PRINT_ERROR)
428 warnx(illoptchar, optchar);
429 optopt = optchar;
430 return (BADCH);
431 }
432 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
433 /* -W long-option */
434 if (*place) /* no space */
435 /* NOTHING */;
436 else if (++optind >= nargc) { /* no arg */
437 place = EMSG;
438 if (PRINT_ERROR)
439 warnx(recargchar, optchar);
440 optopt = optchar;
441 return (BADARG);
442 } else /* white space */
443 place = nargv[optind];
444 optchar = parse_long_options(nargv, options, long_options,
445 idx, 0, flags);
446 place = EMSG;
447 return (optchar);
448 }
449 if (*++oli != ':') { /* doesn't take argument */
450 if (!*place)
451 ++optind;
452 } else { /* takes (optional) argument */
453 optarg = NULL;
454 if (*place) /* no white space */
455 optarg = place;
456 else if (oli[1] != ':') { /* arg not optional */
457 if (++optind >= nargc) { /* no arg */
458 place = EMSG;
459 if (PRINT_ERROR)
460 warnx(recargchar, optchar);
461 optopt = optchar;
462 return (BADARG);
463 } else
464 optarg = nargv[optind];
465 }
466 place = EMSG;
467 ++optind;
468 }
469 /* dump back option letter */
470 return (optchar);
471}
472
473/*
474 * getopt --
475 * Parse argc/argv argument vector.
476 *
477 * [eventually this will replace the BSD getopt]
478 */
479int
480getopt(int nargc, char * const *nargv, const char *options)
481{
482
483 /*
484 * We don't pass FLAG_PERMUTE to getopt_internal() since
485 * the BSD getopt(3) (unlike GNU) has never done this.
486 *
487 * Furthermore, since many privileged programs call getopt()
488 * before dropping privileges it makes sense to keep things
489 * as simple (and bug-free) as possible.
490 */
491 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
492}
493
494/*
495 * getopt_long --
496 * Parse argc/argv argument vector.
497 */
498int
499getopt_long(int nargc, char * const *nargv, const char *options,
500 const struct option *long_options, int *idx)
501{
502
503 return (getopt_internal(nargc, nargv, options, long_options, idx,
504 FLAG_PERMUTE));
505}
506
507/*
508 * getopt_long_only --
509 * Parse argc/argv argument vector.
510 */
511int
512getopt_long_only(int nargc, char * const *nargv, const char *options,
513 const struct option *long_options, int *idx)
514{
515
516 return (getopt_internal(nargc, nargv, options, long_options, idx,
517 FLAG_PERMUTE|FLAG_LONGONLY));
518}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..ef813430de
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,145 @@
1.\" $OpenBSD: getsubopt.3,v 1.13 2013/06/05 03:39:23 tedu 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd $Mdocdate: June 5 2013 $
33.Dt GETSUBOPT 3
34.Os
35.Sh NAME
36.Nm getsubopt
37.Nd get sub options from an argument
38.Sh SYNOPSIS
39.In stdlib.h
40.Vt extern char *suboptarg;
41.Ft int
42.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
43.Sh DESCRIPTION
44The
45.Fn getsubopt
46function parses a string containing tokens delimited by one or more
47tab, space, or comma
48.Pq Ql \&,
49characters.
50It is intended for use in parsing groups of option arguments provided
51as part of a utility command line.
52.Pp
53The argument
54.Fa optionp
55is a pointer to a pointer to the string.
56The argument
57.Fa tokens
58is a pointer to a null-terminated array of pointers to strings.
59.Pp
60The
61.Fn getsubopt
62function returns the zero-based offset of the pointer in the
63.Fa tokens
64array referencing a string which matches the first token
65in the string, or \-1 if the string contains no tokens or
66.Fa tokens
67does not contain a matching string.
68.Pp
69If the token is of the form
70.Ar name Ns = Ns Ar value ,
71the location referenced by
72.Fa valuep
73will be set to point to the start of the
74.Dq value
75portion of the token.
76.Pp
77On return from
78.Fn getsubopt ,
79.Fa optionp
80will be set to point to the start of the next token in the string,
81or the NUL at the end of the string if no more tokens are present.
82The external variable
83.Fa suboptarg
84will be set to point to the start of the current token, or
85.Dv NULL
86if no tokens were present.
87The argument
88.Fa valuep
89will be set to point to the value portion of the token, or
90.Dv NULL
91if no value portion was present.
92.Sh EXAMPLES
93.Bd -literal
94char *tokens[] = {
95 #define ONE 0
96 "one",
97 #define TWO 1
98 "two",
99 NULL
100};
101
102\&...
103
104extern char *optarg, *suboptarg;
105char *options, *value;
106
107while ((ch = getopt(argc, argv, "ab:")) != -1) {
108 switch (ch) {
109 case 'a':
110 /* process ``a'' option */
111 break;
112 case 'b':
113 options = optarg;
114 while (*options) {
115 switch (getsubopt(&options, tokens, &value)) {
116 case ONE:
117 /* process ``one'' sub option */
118 break;
119 case TWO:
120 /* process ``two'' sub option */
121 if (!value)
122 error("no value for two");
123 i = atoi(value);
124 break;
125 case -1:
126 if (suboptarg)
127 error("illegal sub option %s",
128 suboptarg);
129 else
130 error("missing sub option");
131 break;
132 }
133 }
134 break;
135 }
136}
137.Ed
138.Sh SEE ALSO
139.Xr getopt 3 ,
140.Xr strsep 3
141.Sh HISTORY
142The
143.Fn getsubopt
144function first appeared in
145.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..735c85ba8a
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,92 @@
1/* $OpenBSD: getsubopt.c,v 1.4 2005/08/08 08:05:36 espie 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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <unistd.h>
33#include <stdlib.h>
34#include <string.h>
35
36/*
37 * The SVID interface to getsubopt provides no way of figuring out which
38 * part of the suboptions list wasn't matched. This makes error messages
39 * tricky... The extern variable suboptarg is a pointer to the token
40 * which didn't match.
41 */
42char *suboptarg;
43
44int
45getsubopt(char **optionp, char * const *tokens, char **valuep)
46{
47 int cnt;
48 char *p;
49
50 suboptarg = *valuep = NULL;
51
52 if (!optionp || !*optionp)
53 return(-1);
54
55 /* skip leading white-space, commas */
56 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
57
58 if (!*p) {
59 *optionp = p;
60 return(-1);
61 }
62
63 /* save the start of the token, and skip the rest of the token. */
64 for (suboptarg = p;
65 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
66
67 if (*p) {
68 /*
69 * If there's an equals sign, set the value pointer, and
70 * skip over the value part of the token. Terminate the
71 * token.
72 */
73 if (*p == '=') {
74 *p = '\0';
75 for (*valuep = ++p;
76 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
77 if (*p)
78 *p++ = '\0';
79 } else
80 *p++ = '\0';
81 /* Skip any whitespace or commas after this token. */
82 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
83 }
84
85 /* set optionp for next round. */
86 *optionp = p;
87
88 for (cnt = 0; *tokens; ++tokens, ++cnt)
89 if (!strcmp(suboptarg, *tokens))
90 return(cnt);
91 return(-1);
92}
diff --git a/src/lib/libc/stdlib/hcreate.3 b/src/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000000..ea264b57c8
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,239 @@
1.\" $OpenBSD: hcreate.3,v 1.6 2010/07/28 09:00:20 ray Exp $
2.\" $NetBSD: hcreate.3,v 1.8 2010/05/01 06:18:03 jruoho Exp $
3.\"
4.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Klaus Klein.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29.\" POSSIBILITY OF SUCH DAMAGE.
30.\"
31.Dd $Mdocdate: July 28 2010 $
32.Dt HCREATE 3
33.Os
34.Sh NAME
35.Nm hcreate ,
36.Nm hdestroy ,
37.Nm hsearch
38.Nd manage hash search table
39.Sh SYNOPSIS
40.In search.h
41.Ft int
42.Fn hcreate "size_t nel"
43.Ft void
44.Fn hdestroy "void"
45.Ft ENTRY *
46.Fn hsearch "ENTRY item" "ACTION action"
47.Sh DESCRIPTION
48The
49.Fn hcreate ,
50.Fn hdestroy ,
51and
52.Fn hsearch
53functions manage hash search tables.
54.Pp
55The
56.Fn hcreate
57function allocates and initializes the table.
58The
59.Fa nel
60argument specifies an estimate of the maximum number of entries to be held
61by the table.
62Unless further memory allocation fails, supplying an insufficient
63.Fa nel
64value will not result in functional harm, although a performance degradation
65may occur.
66Initialization using the
67.Fn hcreate
68function is mandatory prior to any access operations using
69.Fn hsearch .
70.Pp
71The
72.Fn hdestroy
73function destroys a table previously created using
74.Fn hcreate .
75After a call to
76.Fn hdestroy ,
77the data can no longer be accessed.
78.Pp
79The
80.Fn hsearch
81function is used to search to the hash table.
82It returns a pointer into the
83hash table indicating the address of an item.
84The
85.Fa item
86argument is of type
87.Vt ENTRY ,
88defined in the
89.In search.h
90header.
91This is a structure type that contains two pointers:
92.Pp
93.Bl -tag -compact -offset indent -width "void *data "
94.It Fa char *key
95comparison key
96.It Fa void *data
97pointer to data associated with
98.Fa key
99.El
100.Pp
101The key comparison function used by
102.Fn hsearch
103is
104.Xr strcmp 3 .
105.Pp
106The
107.Fa action
108argument is of type
109.Vt ACTION ,
110an enumeration type which defines the following values:
111.Bl -tag -offset indent -width ENTERXX
112.It Dv ENTER
113Insert
114.Fa item
115into the hash table.
116If an existing item with the same key is found, it is not replaced.
117Note that the
118.Fa key
119and
120.Fa data
121elements of
122.Fa item
123are used directly by the new table entry.
124The storage for the
125key must not be modified during the lifetime of the hash table.
126.It Dv FIND
127Search the hash table without inserting
128.Fa item .
129.El
130.Pp
131Note that the comparison
132.Fa key
133must be allocated using
134.Xr malloc 3
135or
136.Xr calloc 3
137if action is
138.Dv ENTER
139and
140.Fn hdestroy
141will be called.
142This is because
143.Fn hdestroy
144will call
145.Xr free 3
146for each comparison
147.Fa key
148(but not
149.Fa data ) .
150Typically the comparison
151.Fa key
152is allocated by using
153.Xr strdup 3 .
154.Sh RETURN VALUES
155If successful, the
156.Fn hcreate
157function returns a non-zero value.
158Otherwise, a value of 0 is returned and
159.Va errno
160is set to indicate the error.
161.Pp
162The
163.Fn hdestroy
164functions
165returns no value.
166.Pp
167If successful, the
168.Fn hsearch
169function returns a pointer to a hash table entry matching
170the provided key.
171If the action is
172.Dv FIND
173and the item was not found, or if the action is
174.Dv ENTER
175and the insertion failed,
176.Dv NULL
177is returned and
178.Va errno
179is set to indicate the error.
180If the action is
181.Dv ENTER
182and an entry already existed in the table matching the given
183key, the existing entry is returned and is not replaced.
184.Sh ERRORS
185The
186.Fn hcreate
187and
188.Fn hsearch
189functions will fail if:
190.Bl -tag -width Er
191.It Bq Er ENOMEM
192Insufficient memory is available.
193.El
194.Sh SEE ALSO
195.Xr bsearch 3 ,
196.Xr lsearch 3 ,
197.Xr malloc 3 ,
198.Xr strcmp 3
199.Sh STANDARDS
200The
201.Fn hcreate ,
202.Fn hdestroy
203and
204.Fn hsearch
205functions conform to
206.St -xpg4.2 .
207.Sh HISTORY
208The
209.Fn hcreate ,
210.Fn hdestroy
211and
212.Fn hsearch
213functions first appeared in
214.At V .
215.Sh CAVEATS
216At least the following limitations can be mentioned:
217.Bl -bullet
218.It
219The interface permits the use of only one hash table at a time.
220.It
221Individual hash table entries can be added, but not deleted.
222.It
223The standard is indecipherable about the
224internal memory usage of the functions,
225mentioning only that
226.Do
227.Fn hcreate
228and
229.Fn hsearch
230functions may use
231.Fn malloc
232to allocate space
233.Dc .
234This limits the portability of the functions,
235given that other implementations may not
236.Xr free 3
237the buffer pointed by
238.Fa key .
239.El
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000000..094f32c173
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,191 @@
1/* $OpenBSD: hcreate.c,v 1.4 2007/09/02 15:19:17 deraadt Exp $ */
2/* $NetBSD: hcreate.c,v 1.5 2004/04/23 02:48:12 simonb Exp $ */
3
4/*
5 * Copyright (c) 2001 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the
19 * NetBSD Project. See http://www.NetBSD.org/ for
20 * information about NetBSD.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
36 */
37
38/*
39 * hcreate() / hsearch() / hdestroy()
40 *
41 * SysV/XPG4 hash table functions.
42 *
43 * Implementation done based on NetBSD manual page and Solaris manual page,
44 * plus my own personal experience about how they're supposed to work.
45 *
46 * I tried to look at Knuth (as cited by the Solaris manual page), but
47 * nobody had a copy in the office, so...
48 */
49
50#include "namespace.h"
51#include <assert.h>
52#include <errno.h>
53#include <inttypes.h>
54#include <search.h>
55#include <stdlib.h>
56#include <string.h>
57#include <sys/queue.h>
58
59#ifndef _DIAGASSERT
60#define _DIAGASSERT(x)
61#endif
62
63/*
64 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
65 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
66 */
67struct internal_entry {
68 SLIST_ENTRY(internal_entry) link;
69 ENTRY ent;
70};
71SLIST_HEAD(internal_head, internal_entry);
72
73#define MIN_BUCKETS_LG2 4
74#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
75
76/*
77 * max * sizeof internal_entry must fit into size_t.
78 * assumes internal_entry is <= 32 (2^5) bytes.
79 */
80#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
81#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
82
83/* Default hash function, from db/hash/hash_func.c */
84extern u_int32_t (*__default_hash)(const void *, size_t);
85
86static struct internal_head *htable;
87static size_t htablesize;
88
89int
90hcreate(size_t nel)
91{
92 size_t idx;
93 unsigned int p2;
94
95 /* Make sure this isn't called when a table already exists. */
96 _DIAGASSERT(htable == NULL);
97 if (htable != NULL) {
98 errno = EINVAL;
99 return 0;
100 }
101
102 /* If nel is too small, make it min sized. */
103 if (nel < MIN_BUCKETS)
104 nel = MIN_BUCKETS;
105
106 /* If it's too large, cap it. */
107 if (nel > MAX_BUCKETS)
108 nel = MAX_BUCKETS;
109
110 /* If it's is not a power of two in size, round up. */
111 if ((nel & (nel - 1)) != 0) {
112 for (p2 = 0; nel != 0; p2++)
113 nel >>= 1;
114 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
115 nel = 1 << p2;
116 }
117
118 /* Allocate the table. */
119 htablesize = nel;
120 htable = calloc(htablesize, sizeof htable[0]);
121 if (htable == NULL) {
122 errno = ENOMEM;
123 return 0;
124 }
125
126 /* Initialize it. */
127 for (idx = 0; idx < htablesize; idx++)
128 SLIST_INIT(&htable[idx]);
129
130 return 1;
131}
132
133void
134hdestroy(void)
135{
136 struct internal_entry *ie;
137 size_t idx;
138
139 _DIAGASSERT(htable != NULL);
140 if (htable == NULL)
141 return;
142
143 for (idx = 0; idx < htablesize; idx++) {
144 while (!SLIST_EMPTY(&htable[idx])) {
145 ie = SLIST_FIRST(&htable[idx]);
146 SLIST_REMOVE_HEAD(&htable[idx], link);
147 free(ie->ent.key);
148 free(ie);
149 }
150 }
151 free(htable);
152 htable = NULL;
153}
154
155ENTRY *
156hsearch(ENTRY item, ACTION action)
157{
158 struct internal_head *head;
159 struct internal_entry *ie;
160 uint32_t hashval;
161 size_t len;
162
163 _DIAGASSERT(htable != NULL);
164 _DIAGASSERT(item.key != NULL);
165 _DIAGASSERT(action == ENTER || action == FIND);
166
167 len = strlen(item.key);
168 hashval = (*__default_hash)(item.key, len);
169
170 head = &htable[hashval & (htablesize - 1)];
171 ie = SLIST_FIRST(head);
172 while (ie != NULL) {
173 if (strcmp(ie->ent.key, item.key) == 0)
174 break;
175 ie = SLIST_NEXT(ie, link);
176 }
177
178 if (ie != NULL)
179 return &ie->ent;
180 else if (action == FIND)
181 return NULL;
182
183 ie = malloc(sizeof *ie);
184 if (ie == NULL)
185 return NULL;
186 ie->ent.key = item.key;
187 ie->ent.data = item.data;
188
189 SLIST_INSERT_HEAD(head, ie, link);
190 return &ie->ent;
191}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000000..ad3fffbcd9
--- /dev/null
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,173 @@
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
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. 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
33#include <sys/types.h>
34#include <errno.h>
35#include <stdlib.h>
36
37/*
38 * Swap two areas of size number of bytes. Although qsort(3) permits random
39 * blocks of memory to be sorted, sorting pointers is almost certainly the
40 * common case (and, were it not, could easily be made so). Regardless, it
41 * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
42 * arithmetic gets lost in the time required for comparison function calls.
43 */
44#define SWAP(a, b, count, size, tmp) { \
45 count = size; \
46 do { \
47 tmp = *a; \
48 *a++ = *b; \
49 *b++ = tmp; \
50 } while (--count); \
51}
52
53/* Copy one block of size size to another. */
54#define COPY(a, b, count, size, tmp1, tmp2) { \
55 count = size; \
56 tmp1 = a; \
57 tmp2 = b; \
58 do { \
59 *tmp1++ = *tmp2++; \
60 } while (--count); \
61}
62
63/*
64 * Build the list into a heap, where a heap is defined such that for
65 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
66 *
67 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
68 * j < nmemb, select largest of Ki, Kj and Kj+1.
69 */
70#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
71 for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
72 par_i = child_i) { \
73 child = base + child_i * size; \
74 if (child_i < nmemb && compar(child, child + size) < 0) { \
75 child += size; \
76 ++child_i; \
77 } \
78 par = base + par_i * size; \
79 if (compar(child, par) <= 0) \
80 break; \
81 SWAP(par, child, count, size, tmp); \
82 } \
83}
84
85/*
86 * Select the top of the heap and 'heapify'. Since by far the most expensive
87 * action is the call to the compar function, a considerable optimization
88 * in the average case can be achieved due to the fact that k, the displaced
89 * element, is usually quite small, so it would be preferable to first
90 * heapify, always maintaining the invariant that the larger child is copied
91 * over its parent's record.
92 *
93 * Then, starting from the *bottom* of the heap, finding k's correct place,
94 * again maintaining the invariant. As a result of the invariant no element
95 * is 'lost' when k is assigned its correct place in the heap.
96 *
97 * The time savings from this optimization are on the order of 15-20% for the
98 * average case. See Knuth, Vol. 3, page 158, problem 18.
99 *
100 * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
101 */
102#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
103 for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
104 child = base + child_i * size; \
105 if (child_i < nmemb && compar(child, child + size) < 0) { \
106 child += size; \
107 ++child_i; \
108 } \
109 par = base + par_i * size; \
110 COPY(par, child, count, size, tmp1, tmp2); \
111 } \
112 for (;;) { \
113 child_i = par_i; \
114 par_i = child_i / 2; \
115 child = base + child_i * size; \
116 par = base + par_i * size; \
117 if (child_i == 1 || compar(k, par) < 0) { \
118 COPY(child, k, count, size, tmp1, tmp2); \
119 break; \
120 } \
121 COPY(child, par, count, size, tmp1, tmp2); \
122 } \
123}
124
125/*
126 * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
127 * and worst. While heapsort is faster than the worst case of quicksort,
128 * the BSD quicksort does median selection so that the chance of finding
129 * a data set that will trigger the worst case is nonexistent. Heapsort's
130 * only advantage over quicksort is that it requires little additional memory.
131 */
132int
133heapsort(void *vbase, size_t nmemb, size_t size,
134 int (*compar)(const void *, const void *))
135{
136 size_t cnt, i, j, l;
137 char tmp, *tmp1, *tmp2;
138 char *base, *k, *p, *t;
139
140 if (nmemb <= 1)
141 return (0);
142
143 if (!size) {
144 errno = EINVAL;
145 return (-1);
146 }
147
148 if ((k = malloc(size)) == NULL)
149 return (-1);
150
151 /*
152 * Items are numbered from 1 to nmemb, so offset from size bytes
153 * below the starting address.
154 */
155 base = (char *)vbase - size;
156
157 for (l = nmemb / 2 + 1; --l;)
158 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
159
160 /*
161 * For each element of the heap, save the largest element into its
162 * final slot, save the displaced element (k), then recreate the
163 * heap.
164 */
165 while (nmemb > 1) {
166 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
167 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
168 --nmemb;
169 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
170 }
171 free(k);
172 return (0);
173}
diff --git a/src/lib/libc/stdlib/imaxabs.3 b/src/lib/libc/stdlib/imaxabs.3
new file mode 100644
index 0000000000..6c4793477e
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxabs.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: imaxabs.3,v 1.6 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt IMAXABS 3
36.Os
37.Sh NAME
38.Nm imaxabs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.In inttypes.h
42.Ft intmax_t
43.Fn imaxabs "intmax_t j"
44.Sh DESCRIPTION
45The
46.Fn imaxabs
47function computes the absolute value of the intmax_t variable
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn imaxabs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr abs 3 ,
55.Xr cabs 3 ,
56.Xr floor 3 ,
57.Xr hypot 3 ,
58.Xr labs 3
59.Sh STANDARDS
60The
61.Fn imaxabs
62function conforms to
63.St -ansiC-99 .
64.Sh BUGS
65The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/imaxabs.c b/src/lib/libc/stdlib/imaxabs.c
new file mode 100644
index 0000000000..b7e910eefd
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxabs.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: imaxabs.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <inttypes.h>
33
34intmax_t
35imaxabs(intmax_t j)
36{
37 return (j < 0 ? -j : j);
38}
diff --git a/src/lib/libc/stdlib/imaxdiv.3 b/src/lib/libc/stdlib/imaxdiv.3
new file mode 100644
index 0000000000..40ac0bc236
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxdiv.3
@@ -0,0 +1,66 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: imaxdiv.3,v 1.5 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt IMAXDIV 3
36.Os
37.Sh NAME
38.Nm imaxdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.In inttypes.h
42.Ft imaxdiv_t
43.Fn imaxdiv "intmax_t num" "intmax_t denom"
44.Sh DESCRIPTION
45The
46.Fn imaxdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li imaxdiv_t
51that contains two
52.Li intmax_t
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr ldiv 3 ,
60.Xr lldiv 3 ,
61.Xr qdiv 3
62.Sh STANDARDS
63The
64.Fn imaxdiv
65function conforms to
66.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/imaxdiv.c b/src/lib/libc/stdlib/imaxdiv.c
new file mode 100644
index 0000000000..0515a94b96
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxdiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: imaxdiv.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <inttypes.h> /* imaxdiv_t */
35
36imaxdiv_t
37imaxdiv(intmax_t num, intmax_t denom)
38{
39 imaxdiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..64da36a898
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: insque.3,v 1.9 2013/06/05 03:39:23 tedu Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd $Mdocdate: June 5 2013 $
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.In search.h
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superseded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal -offset indent
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Pp
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn insque
87and
88.Fn remque
89functions conform to the
90.St -p1003.1-2001
91and
92.St -xpg4.3
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the
100.Li insque
101and
102.Li remque
103instructions on the
104.Tn VAX .
105They first appeared in
106.Bx 4.2 .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..8724efec74
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: insque.c,v 1.2 2005/08/08 08:05:36 espie Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <search.h>
32
33struct qelem {
34 struct qelem *q_forw;
35 struct qelem *q_back;
36};
37
38void
39insque(void *entry, void *pred)
40{
41 struct qelem *e = (struct qelem *) entry;
42 struct qelem *p = (struct qelem *) pred;
43
44 e->q_forw = p->q_forw;
45 e->q_back = p;
46 p->q_forw->q_back = e;
47 p->q_forw = e;
48}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
new file mode 100644
index 0000000000..cb8c592750
--- /dev/null
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: jrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17long
18jrand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ((long) xseed[2] << 16) + (long) xseed[1];
22}
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000000..4f33df37b2
--- /dev/null
+++ b/src/lib/libc/stdlib/l64a.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: l64a.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <errno.h>
8#include <stdlib.h>
9
10char *
11l64a(long value)
12{
13 static char buf[8];
14 char *s = buf;
15 int digit;
16 int i;
17
18 if (value < 0) {
19 errno = EINVAL;
20 return(NULL);
21 }
22
23 for (i = 0; value != 0 && i < 6; i++) {
24 digit = value & 0x3f;
25
26 if (digit < 2)
27 *s = digit + '.';
28 else if (digit < 12)
29 *s = digit + '0' - 2;
30 else if (digit < 38)
31 *s = digit + 'A' - 12;
32 else
33 *s = digit + 'a' - 38;
34
35 value >>= 6;
36 s++;
37 }
38
39 *s = '\0';
40
41 return(buf);
42}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
new file mode 100644
index 0000000000..a38c64b1af
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.3
@@ -0,0 +1,69 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: labs.3,v 1.12 2014/01/19 05:21:12 schwarze Exp $
33.\"
34.Dd $Mdocdate: January 19 2014 $
35.Dt LABS 3
36.Os
37.Sh NAME
38.Nm labs ,
39.Nm llabs
40.Nd return the absolute value of a long integer
41.Sh SYNOPSIS
42.In stdlib.h
43.Ft long
44.Fn labs "long i"
45.Ft long long
46.Fn llabs "long long j"
47.Sh DESCRIPTION
48The
49.Fn labs
50function returns the absolute value of the long integer
51.Fa i .
52The
53.Fn llabs
54function returns the absolute value of the long long integer
55.Fa j .
56.Sh SEE ALSO
57.Xr abs 3 ,
58.Xr cabs 3 ,
59.Xr floor 3 ,
60.Xr imaxabs 3
61.Sh STANDARDS
62The
63.Fn labs
64and
65.Fn llabs
66functions conform to
67.St -ansiC-99 .
68.Sh BUGS
69The 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
new file mode 100644
index 0000000000..ca60b9aba2
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: labs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33long
34labs(long j)
35{
36 return(j < 0 ? -j : j);
37}
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
new file mode 100644
index 0000000000..2cf5c271ba
--- /dev/null
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -0,0 +1,31 @@
1/* $OpenBSD: lcong48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21void
22lcong48(unsigned short p[7])
23{
24 __rand48_seed[0] = p[0];
25 __rand48_seed[1] = p[1];
26 __rand48_seed[2] = p[2];
27 __rand48_mult[0] = p[3];
28 __rand48_mult[1] = p[4];
29 __rand48_mult[2] = p[5];
30 __rand48_add = p[6];
31}
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
new file mode 100644
index 0000000000..a8835ab6ac
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,72 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: ldiv.3,v 1.12 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt LDIV 3
36.Os
37.Sh NAME
38.Nm ldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft ldiv_t
43.Fn ldiv "long num" "long denom"
44.Sh DESCRIPTION
45The
46.Fn ldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li ldiv_t
51that contains two
52.Li long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr imaxdiv 3 ,
60.Xr lldiv 3 ,
61.Xr qdiv 3
62.Sh STANDARDS
63The
64.Fn ldiv
65function conforms to
66.St -ansiC .
67.Sh HISTORY
68An
69.Fn ldiv
70function with similar functionality, but a different calling convention,
71first appeared in
72.At v4 .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000000..775065f525
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: ldiv.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <stdlib.h> /* ldiv_t */
35
36ldiv_t
37ldiv(long num, long denom)
38{
39 ldiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/llabs.c b/src/lib/libc/stdlib/llabs.c
new file mode 100644
index 0000000000..fc2cd8261c
--- /dev/null
+++ b/src/lib/libc/stdlib/llabs.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: llabs.c,v 1.3 2007/01/08 19:39:25 deraadt Exp $ */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <stdlib.h>
33
34long long
35llabs(long long j)
36{
37 return (j < 0 ? -j : j);
38}
diff --git a/src/lib/libc/stdlib/lldiv.3 b/src/lib/libc/stdlib/lldiv.3
new file mode 100644
index 0000000000..9181f8b7c5
--- /dev/null
+++ b/src/lib/libc/stdlib/lldiv.3
@@ -0,0 +1,66 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: lldiv.3,v 1.4 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt LLDIV 3
36.Os
37.Sh NAME
38.Nm lldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft lldiv_t
43.Fn lldiv "long long num" "long long denom"
44.Sh DESCRIPTION
45The
46.Fn lldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li lldiv_t
51that contains two
52.Li long long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr imaxdiv 3 ,
60.Xr ldiv 3 ,
61.Xr qdiv 3
62.Sh STANDARDS
63The
64.Fn lldiv
65function conforms to
66.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/lldiv.c b/src/lib/libc/stdlib/lldiv.c
new file mode 100644
index 0000000000..e8d6c978b3
--- /dev/null
+++ b/src/lib/libc/stdlib/lldiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: lldiv.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <stdlib.h> /* lldiv_t */
35
36lldiv_t
37lldiv(long long num, long long denom)
38{
39 lldiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
new file mode 100644
index 0000000000..21beb858ca
--- /dev/null
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: lrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19long
20lrand48(void)
21{
22 __dorand48(__rand48_seed);
23 return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1);
24}
diff --git a/src/lib/libc/stdlib/lsearch.3 b/src/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000000..c5a55980e1
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,108 @@
1.\" $OpenBSD: lsearch.3,v 1.10 2013/06/05 03:39:23 tedu Exp $
2.\"
3.\" Copyright (c) 1989, 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
31.\"
32.Dd $Mdocdate: June 5 2013 $
33.Dt LSEARCH 3
34.Os
35.Sh NAME
36.Nm lsearch ,
37.Nm lfind
38.Nd linear searching routines
39.Sh SYNOPSIS
40.In search.h
41.Ft char *
42.Fn lsearch "const void *key" "const void *base" "size_t *nelp" \
43 "size_t width" "int (*compar)(const void *, const void *)"
44.Ft char *
45.Fn lfind "const void *key" "const void *base" "size_t *nelp" \
46 "size_t width" "int (*compar)(const void *, const void *)"
47.Sh DESCRIPTION
48The functions
49.Fn lsearch
50and
51.Fn lfind
52provide basic linear searching functionality.
53.Pp
54.Fa base
55is the pointer to the beginning of an array.
56The argument
57.Fa nelp
58is the current number of elements in the array, where each element
59is
60.Fa width
61bytes long.
62The
63.Fa compar
64function
65is a comparison routine which is used to compare two elements.
66It takes two arguments which point to the
67.Fa key
68object and to an array member, in that order, and must return an integer
69less than, equivalent to, or greater than zero if the
70.Fa key
71object is considered, respectively, to be less than, equal to, or greater
72than the array member.
73.Pp
74The
75.Fn lsearch
76and
77.Fn lfind
78functions
79return a pointer into the array referenced by
80.Fa base
81where
82.Fa key
83is located.
84If
85.Fa key
86does not exist,
87.Fn lfind
88will return a null pointer and
89.Fn lsearch
90will add it to the array.
91When an element is added to the array by
92.Fn lsearch ,
93the location referenced by the argument
94.Fa nelp
95is incremented by one.
96.Sh SEE ALSO
97.Xr bsearch 3 ,
98.Xr db 3
99.Sh STANDARDS
100The
101.Fn lsearch
102and
103.Fn lfind
104functions conform to the
105.St -p1003.1-2001
106and
107.St -xpg4.3
108specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..a01d80e008
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,84 @@
1/* $OpenBSD: lsearch.c,v 1.4 2009/10/27 23:59:59 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Roger L. Snyder.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. 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
35#include <sys/types.h>
36#include <string.h>
37#include <search.h>
38
39typedef int (*cmp_fn_t)(const void *, const void *);
40static void *linear_base(const void *, const void *, size_t *, size_t,
41 cmp_fn_t, int);
42
43void *
44lsearch(const void *key, const void *base, size_t *nelp, size_t width,
45 cmp_fn_t compar)
46{
47
48 return(linear_base(key, base, nelp, width, compar, 1));
49}
50
51void *
52lfind(const void *key, const void *base, size_t *nelp, size_t width,
53 cmp_fn_t compar)
54{
55 return(linear_base(key, base, nelp, width, compar, 0));
56}
57
58static void *
59linear_base(const void *key, const void *base, size_t *nelp, size_t width,
60 cmp_fn_t compar, int add_flag)
61{
62 const char *element, *end;
63
64 end = (const char *)base + *nelp * width;
65 for (element = base; element < end; element += width)
66 if (!compar(key, element)) /* key found */
67 return((void *)element);
68
69 if (!add_flag) /* key not found */
70 return(NULL);
71
72 /*
73 * The UNIX System User's Manual, 1986 edition claims that
74 * a NULL pointer is returned by lsearch with errno set
75 * appropriately, if there is not enough room in the table
76 * to add a new item. This can't be done as none of these
77 * routines have any method of determining the size of the
78 * table. This comment isn't in the 1986-87 System V
79 * manual.
80 */
81 ++*nelp;
82 memcpy((void *)end, key, width);
83 return((void *)end);
84}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
new file mode 100644
index 0000000000..414f0a9770
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,484 @@
1.\"
2.\" Copyright (c) 1980, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" This code is derived from software contributed to Berkeley by
6.\" the American National Standards Committee X3, on Information
7.\" Processing Systems.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution.
17.\" 3. Neither the name of the University nor the names of its contributors
18.\" may be used to endorse or promote products derived from this software
19.\" without specific prior written permission.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE.
32.\"
33.\" $OpenBSD: malloc.3,v 1.73 2013/07/18 10:14:49 schwarze Exp $
34.\"
35.Dd $Mdocdate: July 18 2013 $
36.Dt MALLOC 3
37.Os
38.Sh NAME
39.Nm malloc ,
40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm cfree
44.Nd memory allocation and deallocation
45.Sh SYNOPSIS
46.In stdlib.h
47.Ft void *
48.Fn malloc "size_t size"
49.Ft void *
50.Fn calloc "size_t nmemb" "size_t size"
51.Ft void *
52.Fn realloc "void *ptr" "size_t size"
53.Ft void
54.Fn free "void *ptr"
55.Ft void
56.Fn cfree "void *ptr"
57.Ft char *
58.Va malloc_options ;
59.Sh DESCRIPTION
60The
61.Fn malloc
62function allocates uninitialized space for an object whose
63size is specified by
64.Fa size .
65The
66.Fn malloc
67function maintains multiple lists of free blocks according to size, allocating
68space from the appropriate list.
69.Pp
70The allocated space is
71suitably aligned (after possible pointer
72coercion) for storage of any type of object.
73If the space is of
74.Em pagesize
75or larger, the memory returned will be page-aligned.
76.Pp
77Allocation of a zero size object returns a pointer to a zero size object.
78This zero size object is access protected, so any access to it will
79generate an exception (SIGSEGV).
80Many zero-sized objects can be placed consecutively in shared
81protected pages.
82The minimum size of the protection on each object is suitably aligned and
83sized as previously stated, but the protection may extend further depending
84on where in a protected zone the object lands.
85.Pp
86When using
87.Fn malloc
88be careful to avoid the following idiom:
89.Bd -literal -offset indent
90if ((p = malloc(num * size)) == NULL)
91 err(1, "malloc");
92.Ed
93.Pp
94The multiplication may lead to an integer overflow.
95To avoid this,
96.Fn calloc
97is recommended.
98.Pp
99If
100.Fn malloc
101must be used, be sure to test for overflow:
102.Bd -literal -offset indent
103if (size && num > SIZE_MAX / size) {
104 errno = ENOMEM;
105 err(1, "overflow");
106}
107.Ed
108.Pp
109The
110.Fn calloc
111function allocates space for an array of
112.Fa nmemb
113objects, each of whose size is
114.Fa size .
115The space is initialized to zero.
116The use of
117.Fn calloc
118is strongly encouraged when allocating multiple sized objects
119in order to avoid possible integer overflows.
120.Pp
121The
122.Fn free
123function causes the space pointed to by
124.Fa ptr
125to be either placed on a list of free pages to make it available for future
126allocation or, if required, to be returned to the kernel using
127.Xr munmap 2 .
128If
129.Fa ptr
130is a null pointer, no action occurs.
131.Pp
132A
133.Fn cfree
134function is also provided for compatibility with old systems and other
135.Nm malloc
136libraries; it is simply an alias for
137.Fn free .
138.Pp
139The
140.Fn realloc
141function changes the size of the object pointed to by
142.Fa ptr
143to
144.Fa size
145bytes and returns a pointer to the (possibly moved) object.
146The contents of the object are unchanged up to the lesser
147of the new and old sizes.
148If the new size is larger, the value of the newly allocated portion
149of the object is indeterminate and uninitialized.
150If
151.Fa ptr
152is a null pointer, the
153.Fn realloc
154function behaves like the
155.Fn malloc
156function for the specified size.
157If the space cannot be allocated, the object
158pointed to by
159.Fa ptr
160is unchanged.
161If
162.Fa size
163is zero and
164.Fa ptr
165is not a null pointer, the object it points to is freed and a new zero size
166object is returned.
167.Pp
168When using
169.Fn realloc
170be careful to avoid the following idiom:
171.Bd -literal -offset indent
172size += 50;
173if ((p = realloc(p, size)) == NULL)
174 return (NULL);
175.Ed
176.Pp
177Do not adjust the variable describing how much memory has been allocated
178until the allocation has been successful.
179This can cause aberrant program behavior if the incorrect size value is used.
180In most cases, the above sample will also result in a leak of memory.
181As stated earlier, a return value of
182.Dv NULL
183indicates that the old object still remains allocated.
184Better code looks like this:
185.Bd -literal -offset indent
186newsize = size + 50;
187if ((newp = realloc(p, newsize)) == NULL) {
188 free(p);
189 p = NULL;
190 size = 0;
191 return (NULL);
192}
193p = newp;
194size = newsize;
195.Ed
196.Pp
197As with
198.Fn malloc
199it is important to ensure the new size value will not overflow;
200i.e. avoid allocations like the following:
201.Bd -literal -offset indent
202if ((newp = realloc(p, num * size)) == NULL) {
203 ...
204.Ed
205.Sh MALLOC_OPTIONS
206Malloc will first look for a symbolic link called
207.Pa /etc/malloc.conf
208and next check the environment for a variable called
209.Ev MALLOC_OPTIONS
210and finally for the global variable
211.Va malloc_options
212and scan them for flags in that order.
213Flags are single letters, uppercase means on, lowercase means off.
214.Bl -tag -width indent
215.It Cm A
216.Dq Abort .
217.Fn malloc
218will coredump the process, rather than tolerate internal
219inconsistencies or incorrect usage.
220This is the default and a very handy debugging aid,
221since the core file represents the time of failure,
222rather than when the bogus pointer was used.
223.It Cm D
224.Dq Dump .
225.Fn malloc
226will dump statistics to the file
227.Pa ./malloc.out ,
228if it already exists,
229at exit.
230This option requires the library to have been compiled with -DMALLOC_STATS in
231order to have any effect.
232.It Cm F
233.Dq Freeguard .
234Enable use after free detection.
235Unused pages on the freelist are read and write protected to
236cause a segmentation fault upon access.
237This will also switch off the delayed freeing of chunks,
238reducing random behaviour but detecting double
239.Fn free
240calls as early as possible.
241This option is intended for debugging rather than improved security
242(use the
243.Cm U
244option for security).
245.It Cm G
246.Dq Guard .
247Enable guard pages.
248Each page size or larger allocation is followed by a guard page that will
249cause a segmentation fault upon any access.
250.It Cm H
251.Dq Hint .
252Pass a hint to the kernel about pages we don't use.
253If the machine is paging a lot this may help a bit.
254.It Cm J
255.Dq Junk .
256Fill some junk into the area allocated.
257Currently junk is bytes of 0xd0 when allocating; this is pronounced
258.Dq Duh .
259\&:-)
260Freed chunks are filled with 0xdf.
261.It Cm P
262.Dq Move allocations within a page.
263Allocations larger than half a page but smaller than a page
264are aligned to the end of a page to catch buffer overruns in more
265cases.
266This is the default.
267.It Cm R
268.Dq realloc .
269Always reallocate when
270.Fn realloc
271is called, even if the initial allocation was big enough.
272This can substantially aid in compacting memory.
273.\".Pp
274.\".It Cm U
275.\".Dq utrace .
276.\"Generate entries for
277.\".Xr ktrace 1
278.\"for all operations.
279.\"Consult the source for this one.
280.It Cm S
281Enable all options suitable for security auditing.
282.It Cm U
283.Dq Free unmap .
284Enable use after free protection for larger allocations.
285Unused pages on the freelist are read and write protected to
286cause a segmentation fault upon access.
287.It Cm X
288.Dq xmalloc .
289Rather than return failure,
290.Xr abort 3
291the program with a diagnostic message on stderr.
292It is the intention that this option be set at compile time by
293including in the source:
294.Bd -literal -offset indent
295extern char *malloc_options;
296malloc_options = "X";
297.Ed
298.Pp
299Note that this will cause code that is supposed to handle
300out-of-memory conditions gracefully to abort instead.
301.It Cm Z
302.Dq Zero .
303Fill some junk into the area allocated (see
304.Cm J ) ,
305except for the exact length the user asked for, which is zeroed.
306.It Cm <
307.Dq Half the cache size .
308Decrease the size of the free page cache by a factor of two.
309.It Cm >
310.Dq Double the cache size .
311Increase the size of the free page cache by a factor of two.
312.El
313.Pp
314So to set a systemwide reduction of the cache to a quarter of the
315default size and use guard pages:
316.Dl # ln -s 'G\*(Lt\*(Lt' /etc/malloc.conf
317.Pp
318The flags are mostly for testing and debugging.
319If a program changes behavior if any of these options (except
320.Cm X )
321are used,
322it is buggy.
323.Pp
324The default number of free pages cached is 64.
325.Sh RETURN VALUES
326The
327.Fn malloc
328and
329.Fn calloc
330functions return a pointer to the allocated space if successful; otherwise,
331a null pointer is returned and
332.Va errno
333is set to
334.Er ENOMEM .
335.Pp
336The
337.Fn free
338and
339.Fn cfree
340functions return no value.
341.Pp
342The
343.Fn realloc
344function returns a pointer to the (possibly moved) allocated space
345if successful; otherwise, a null pointer is returned and
346.Va errno
347is set to
348.Er ENOMEM .
349.Sh ENVIRONMENT
350.Bl -tag -width Ev
351.It Ev MALLOC_OPTIONS
352See above.
353.El
354.Sh FILES
355.Bl -tag -width "/etc/malloc.conf"
356.It Pa /etc/malloc.conf
357symbolic link to filename containing option flags
358.El
359.Sh DIAGNOSTICS
360If
361.Fn malloc ,
362.Fn calloc ,
363.Fn realloc ,
364or
365.Fn free
366detect an error condition,
367a message will be printed to file descriptor
3682 (not using stdio).
369Errors will result in the process being aborted,
370unless the
371.Cm a
372option has been specified.
373.Pp
374Here is a brief description of the error messages and what they mean:
375.Bl -tag -width Ds
376.It Dq out of memory
377If the
378.Cm X
379option is specified it is an error for
380.Fn malloc ,
381.Fn calloc ,
382or
383.Fn realloc
384to return
385.Dv NULL .
386.It Dq malloc init mmap failed
387This is a rather weird condition that is most likely to indicate a
388seriously overloaded system or a ulimit restriction.
389.It Dq bogus pointer (double free?)
390An attempt to
391.Fn free
392or
393.Fn realloc
394an unallocated pointer was made.
395.It Dq chunk is already free
396There was an attempt to free a chunk that had already been freed.
397.It Dq modified chunk-pointer
398The pointer passed to
399.Fn free
400or
401.Fn realloc
402has been modified.
403.It Dq recursive call
404An attempt was made to call recursively into these functions, i.e., from a
405signal handler.
406This behavior is not supported.
407In particular, signal handlers should
408.Em not
409use any of the
410.Fn malloc
411functions nor utilize any other functions which may call
412.Fn malloc
413(e.g.,
414.Xr stdio 3
415routines).
416.It Dq unknown char in MALLOC_OPTIONS
417We found something we didn't understand.
418.It Dq malloc cache overflow/underflow
419The internal malloc page cache has been corrupted.
420.It Dq malloc free slot lost
421The internal malloc page cache has been corrupted.
422.It Dq guard size
423An inconsistent guard size was detected.
424.It any other error
425.Fn malloc
426detected an internal error;
427consult sources and/or wizards.
428.El
429.Sh SEE ALSO
430.Xr brk 2 ,
431.Xr mmap 2 ,
432.Xr munmap 2 ,
433.Xr alloca 3 ,
434.Xr getpagesize 3 ,
435.Xr posix_memalign 3
436.Sh STANDARDS
437The
438.Fn malloc
439function conforms to
440.St -ansiC .
441.Sh HISTORY
442A
443.Fn free
444internal kernel function and a predecessor to
445.Fn malloc ,
446.Fn alloc ,
447first appeared in
448.At v1 .
449C library functions
450.Fn alloc
451and
452.Fn free
453appeared in
454.At v6 .
455The functions
456.Fn malloc ,
457.Fn calloc ,
458and
459.Fn realloc
460first appeared in
461.At v7 .
462.Pp
463A new implementation by Chris Kingsley was introduced in
464.Bx 4.2 ,
465followed by a complete rewrite by Poul-Henning Kamp which appeared in
466.Fx 2.2
467and was included in
468.Ox 2.0 .
469These implementations were all
470.Xr sbrk 2
471based.
472In
473.Ox 3.8 ,
474Thierry Deval rewrote
475.Nm
476to use the
477.Xr mmap 2
478system call,
479making the page addresses returned by
480.Nm
481random.
482A rewrite by Otto Moerbeek introducing a new central data structure and more
483randomization appeared in
484.Ox 4.4 .
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000000..2cd443191d
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1824 @@
1/* $OpenBSD: malloc.c,v 1.153 2014/04/14 10:29:41 otto Exp $ */
2/*
3 * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
5 * Copyright (c) 2008 Damien Miller <djm@openbsd.org>
6 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21/*
22 * If we meet some day, and you think this stuff is worth it, you
23 * can buy me a beer in return. Poul-Henning Kamp
24 */
25
26/* #define MALLOC_STATS */
27
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/queue.h>
31#include <sys/mman.h>
32#include <sys/uio.h>
33#include <errno.h>
34#include <stdint.h>
35#include <stdlib.h>
36#include <string.h>
37#include <stdio.h>
38#include <unistd.h>
39
40#ifdef MALLOC_STATS
41#include <sys/tree.h>
42#include <fcntl.h>
43#endif
44
45#include "thread_private.h"
46
47#if defined(__sparc__) && !defined(__sparcv9__)
48#define MALLOC_PAGESHIFT (13U)
49#elif defined(__mips64__)
50#define MALLOC_PAGESHIFT (14U)
51#else
52#define MALLOC_PAGESHIFT (PAGE_SHIFT)
53#endif
54
55#define MALLOC_MINSHIFT 4
56#define MALLOC_MAXSHIFT (MALLOC_PAGESHIFT - 1)
57#define MALLOC_PAGESIZE (1UL << MALLOC_PAGESHIFT)
58#define MALLOC_MINSIZE (1UL << MALLOC_MINSHIFT)
59#define MALLOC_PAGEMASK (MALLOC_PAGESIZE - 1)
60#define MASK_POINTER(p) ((void *)(((uintptr_t)(p)) & ~MALLOC_PAGEMASK))
61
62#define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT)
63#define MALLOC_MAXCACHE 256
64#define MALLOC_DELAYED_CHUNKS 15 /* max of getrnibble() */
65#define MALLOC_INITIAL_REGIONS 512
66#define MALLOC_DEFAULT_CACHE 64
67
68/*
69 * When the P option is active, we move allocations between half a page
70 * and a whole page towards the end, subject to alignment constraints.
71 * This is the extra headroom we allow. Set to zero to be the most
72 * strict.
73 */
74#define MALLOC_LEEWAY 0
75
76#define PAGEROUND(x) (((x) + (MALLOC_PAGEMASK)) & ~MALLOC_PAGEMASK)
77
78/*
79 * What to use for Junk. This is the byte value we use to fill with
80 * when the 'J' option is enabled. Use SOME_JUNK right after alloc,
81 * and SOME_FREEJUNK right before free.
82 */
83#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
84#define SOME_FREEJUNK 0xdf
85
86#define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
87 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
88
89#define MMAPA(a,sz) mmap((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
90 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
91
92#define MQUERY(a, sz) mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
93 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t)0)
94
95struct region_info {
96 void *p; /* page; low bits used to mark chunks */
97 uintptr_t size; /* size for pages, or chunk_info pointer */
98#ifdef MALLOC_STATS
99 void *f; /* where allocated from */
100#endif
101};
102
103LIST_HEAD(chunk_head, chunk_info);
104
105struct dir_info {
106 u_int32_t canary1;
107 struct region_info *r; /* region slots */
108 size_t regions_total; /* number of region slots */
109 size_t regions_free; /* number of free slots */
110 /* lists of free chunk info structs */
111 struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1];
112 /* lists of chunks with free slots */
113 struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1];
114 size_t free_regions_size; /* free pages cached */
115 /* free pages cache */
116 struct region_info free_regions[MALLOC_MAXCACHE];
117 /* delayed free chunk slots */
118 void *delayed_chunks[MALLOC_DELAYED_CHUNKS + 1];
119 u_short chunk_start;
120#ifdef MALLOC_STATS
121 size_t inserts;
122 size_t insert_collisions;
123 size_t finds;
124 size_t find_collisions;
125 size_t deletes;
126 size_t delete_moves;
127 size_t cheap_realloc_tries;
128 size_t cheap_reallocs;
129#define STATS_INC(x) ((x)++)
130#define STATS_ZERO(x) ((x) = 0)
131#define STATS_SETF(x,y) ((x)->f = (y))
132#else
133#define STATS_INC(x) /* nothing */
134#define STATS_ZERO(x) /* nothing */
135#define STATS_SETF(x,y) /* nothing */
136#endif /* MALLOC_STATS */
137 u_int32_t canary2;
138};
139#define DIR_INFO_RSZ ((sizeof(struct dir_info) + MALLOC_PAGEMASK) & \
140 ~MALLOC_PAGEMASK)
141
142/*
143 * This structure describes a page worth of chunks.
144 *
145 * How many bits per u_short in the bitmap
146 */
147#define MALLOC_BITS (NBBY * sizeof(u_short))
148struct chunk_info {
149 LIST_ENTRY(chunk_info) entries;
150 void *page; /* pointer to the page */
151 u_int32_t canary;
152 u_short size; /* size of this page's chunks */
153 u_short shift; /* how far to shift for this size */
154 u_short free; /* how many free chunks */
155 u_short total; /* how many chunk */
156 /* which chunks are free */
157 u_short bits[1];
158};
159
160struct malloc_readonly {
161 struct dir_info *g_pool; /* Main bookkeeping information */
162 int malloc_abort; /* abort() on error */
163 int malloc_freenow; /* Free quickly - disable chunk rnd */
164 int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
165 int malloc_hint; /* call madvice on free pages? */
166 int malloc_junk; /* junk fill? */
167 int malloc_move; /* move allocations to end of page? */
168 int malloc_realloc; /* always realloc? */
169 int malloc_xmalloc; /* xmalloc behaviour? */
170 int malloc_zero; /* zero fill? */
171 size_t malloc_guard; /* use guard pages after allocations? */
172 u_int malloc_cache; /* free pages we cache */
173#ifdef MALLOC_STATS
174 int malloc_stats; /* dump statistics at end */
175#endif
176 u_int32_t malloc_canary; /* Matched against ones in g_pool */
177};
178
179/* This object is mapped PROT_READ after initialisation to prevent tampering */
180static union {
181 struct malloc_readonly mopts;
182 u_char _pad[MALLOC_PAGESIZE];
183} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)));
184#define mopts malloc_readonly.mopts
185#define g_pool mopts.g_pool
186
187char *malloc_options; /* compile-time options */
188
189static char *malloc_func; /* current function */
190static int malloc_active; /* status of malloc */
191
192static size_t malloc_guarded; /* bytes used for guards */
193static size_t malloc_used; /* bytes allocated */
194
195static size_t rnibblesused; /* random nibbles used */
196static u_char rbytes[512]; /* random bytes */
197static u_char getrnibble(void);
198
199extern char *__progname;
200
201#ifdef MALLOC_STATS
202void malloc_dump(int);
203static void malloc_exit(void);
204#define CALLER __builtin_return_address(0)
205#else
206#define CALLER NULL
207#endif
208
209/* low bits of r->p determine size: 0 means >= page size and p->size holding
210 * real size, otherwise r->size is a shift count, or 1 for malloc(0)
211 */
212#define REALSIZE(sz, r) \
213 (sz) = (uintptr_t)(r)->p & MALLOC_PAGEMASK, \
214 (sz) = ((sz) == 0 ? (r)->size : ((sz) == 1 ? 0 : (1 << ((sz)-1))))
215
216static inline size_t
217hash(void *p)
218{
219 size_t sum;
220 union {
221 uintptr_t p;
222 unsigned short a[sizeof(void *) / sizeof(short)];
223 } u;
224 u.p = (uintptr_t)p >> MALLOC_PAGESHIFT;
225 sum = u.a[0];
226 sum = (sum << 7) - sum + u.a[1];
227#ifdef __LP64__
228 sum = (sum << 7) - sum + u.a[2];
229 sum = (sum << 7) - sum + u.a[3];
230#endif
231 return sum;
232}
233
234static void
235wrterror(char *msg, void *p)
236{
237 char *q = " error: ";
238 struct iovec iov[7];
239 char pidbuf[20];
240 char buf[20];
241 int saved_errno = errno;
242
243 iov[0].iov_base = __progname;
244 iov[0].iov_len = strlen(__progname);
245 iov[1].iov_base = pidbuf;
246 snprintf(pidbuf, sizeof(pidbuf), "(%d)", getpid());
247 iov[1].iov_len = strlen(pidbuf);
248 iov[2].iov_base = malloc_func;
249 iov[2].iov_len = strlen(malloc_func);
250 iov[3].iov_base = q;
251 iov[3].iov_len = strlen(q);
252 iov[4].iov_base = msg;
253 iov[4].iov_len = strlen(msg);
254 iov[5].iov_base = buf;
255 if (p == NULL)
256 iov[5].iov_len = 0;
257 else {
258 snprintf(buf, sizeof(buf), " %p", p);
259 iov[5].iov_len = strlen(buf);
260 }
261 iov[6].iov_base = "\n";
262 iov[6].iov_len = 1;
263 writev(STDERR_FILENO, iov, 7);
264
265#ifdef MALLOC_STATS
266 if (mopts.malloc_stats)
267 malloc_dump(STDERR_FILENO);
268#endif /* MALLOC_STATS */
269
270 errno = saved_errno;
271 if (mopts.malloc_abort)
272 abort();
273}
274
275static void
276rbytes_init(void)
277{
278 arc4random_buf(rbytes, sizeof(rbytes));
279 rnibblesused = 0;
280}
281
282static inline u_char
283getrnibble(void)
284{
285 u_char x;
286
287 if (rnibblesused >= 2 * sizeof(rbytes))
288 rbytes_init();
289 x = rbytes[rnibblesused++ / 2];
290 return (rnibblesused & 1 ? x & 0xf : x >> 4);
291}
292
293/*
294 * Cache maintenance. We keep at most malloc_cache pages cached.
295 * If the cache is becoming full, unmap pages in the cache for real,
296 * and then add the region to the cache
297 * Opposed to the regular region data structure, the sizes in the
298 * cache are in MALLOC_PAGESIZE units.
299 */
300static void
301unmap(struct dir_info *d, void *p, size_t sz)
302{
303 size_t psz = sz >> MALLOC_PAGESHIFT;
304 size_t rsz, tounmap;
305 struct region_info *r;
306 u_int i, offset;
307
308 if (sz != PAGEROUND(sz)) {
309 wrterror("munmap round", NULL);
310 return;
311 }
312
313 if (psz > mopts.malloc_cache) {
314 if (munmap(p, sz))
315 wrterror("munmap", p);
316 malloc_used -= sz;
317 return;
318 }
319 tounmap = 0;
320 rsz = mopts.malloc_cache - d->free_regions_size;
321 if (psz > rsz)
322 tounmap = psz - rsz;
323 offset = getrnibble() + (getrnibble() << 4);
324 for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) {
325 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
326 if (r->p != NULL) {
327 rsz = r->size << MALLOC_PAGESHIFT;
328 if (munmap(r->p, rsz))
329 wrterror("munmap", r->p);
330 r->p = NULL;
331 if (tounmap > r->size)
332 tounmap -= r->size;
333 else
334 tounmap = 0;
335 d->free_regions_size -= r->size;
336 r->size = 0;
337 malloc_used -= rsz;
338 }
339 }
340 if (tounmap > 0)
341 wrterror("malloc cache underflow", NULL);
342 for (i = 0; i < mopts.malloc_cache; i++) {
343 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
344 if (r->p == NULL) {
345 if (mopts.malloc_hint)
346 madvise(p, sz, MADV_FREE);
347 if (mopts.malloc_freeunmap)
348 mprotect(p, sz, PROT_NONE);
349 r->p = p;
350 r->size = psz;
351 d->free_regions_size += psz;
352 break;
353 }
354 }
355 if (i == mopts.malloc_cache)
356 wrterror("malloc free slot lost", NULL);
357 if (d->free_regions_size > mopts.malloc_cache)
358 wrterror("malloc cache overflow", NULL);
359}
360
361static void
362zapcacheregion(struct dir_info *d, void *p, size_t len)
363{
364 u_int i;
365 struct region_info *r;
366 size_t rsz;
367
368 for (i = 0; i < mopts.malloc_cache; i++) {
369 r = &d->free_regions[i];
370 if (r->p >= p && r->p <= (void *)((char *)p + len)) {
371 rsz = r->size << MALLOC_PAGESHIFT;
372 if (munmap(r->p, rsz))
373 wrterror("munmap", r->p);
374 r->p = NULL;
375 d->free_regions_size -= r->size;
376 r->size = 0;
377 malloc_used -= rsz;
378 }
379 }
380}
381
382static void *
383map(struct dir_info *d, size_t sz, int zero_fill)
384{
385 size_t psz = sz >> MALLOC_PAGESHIFT;
386 struct region_info *r, *big = NULL;
387 u_int i, offset;
388 void *p;
389
390 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
391 d->canary1 != ~d->canary2)
392 wrterror("internal struct corrupt", NULL);
393 if (sz != PAGEROUND(sz)) {
394 wrterror("map round", NULL);
395 return MAP_FAILED;
396 }
397 if (psz > d->free_regions_size) {
398 p = MMAP(sz);
399 if (p != MAP_FAILED)
400 malloc_used += sz;
401 /* zero fill not needed */
402 return p;
403 }
404 offset = getrnibble() + (getrnibble() << 4);
405 for (i = 0; i < mopts.malloc_cache; i++) {
406 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
407 if (r->p != NULL) {
408 if (r->size == psz) {
409 p = r->p;
410 if (mopts.malloc_freeunmap)
411 mprotect(p, sz, PROT_READ | PROT_WRITE);
412 if (mopts.malloc_hint)
413 madvise(p, sz, MADV_NORMAL);
414 r->p = NULL;
415 r->size = 0;
416 d->free_regions_size -= psz;
417 if (zero_fill)
418 memset(p, 0, sz);
419 else if (mopts.malloc_junk &&
420 mopts.malloc_freeunmap)
421 memset(p, SOME_FREEJUNK, sz);
422 return p;
423 } else if (r->size > psz)
424 big = r;
425 }
426 }
427 if (big != NULL) {
428 r = big;
429 p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
430 if (mopts.malloc_freeunmap)
431 mprotect(p, sz, PROT_READ | PROT_WRITE);
432 if (mopts.malloc_hint)
433 madvise(p, sz, MADV_NORMAL);
434 r->size -= psz;
435 d->free_regions_size -= psz;
436 if (zero_fill)
437 memset(p, 0, sz);
438 else if (mopts.malloc_junk && mopts.malloc_freeunmap)
439 memset(p, SOME_FREEJUNK, sz);
440 return p;
441 }
442 p = MMAP(sz);
443 if (p != MAP_FAILED)
444 malloc_used += sz;
445 if (d->free_regions_size > mopts.malloc_cache)
446 wrterror("malloc cache", NULL);
447 /* zero fill not needed */
448 return p;
449}
450
451/*
452 * Initialize a dir_info, which should have been cleared by caller
453 */
454static int
455omalloc_init(struct dir_info **dp)
456{
457 char *p, b[64];
458 int i, j;
459 size_t d_avail, regioninfo_size;
460 struct dir_info *d;
461
462 rbytes_init();
463
464 /*
465 * Default options
466 */
467 mopts.malloc_abort = 1;
468 mopts.malloc_move = 1;
469 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
470
471 for (i = 0; i < 3; i++) {
472 switch (i) {
473 case 0:
474 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
475 if (j <= 0)
476 continue;
477 b[j] = '\0';
478 p = b;
479 break;
480 case 1:
481 if (issetugid() == 0)
482 p = getenv("MALLOC_OPTIONS");
483 else
484 continue;
485 break;
486 case 2:
487 p = malloc_options;
488 break;
489 default:
490 p = NULL;
491 }
492
493 for (; p != NULL && *p != '\0'; p++) {
494 switch (*p) {
495 case '>':
496 mopts.malloc_cache <<= 1;
497 if (mopts.malloc_cache > MALLOC_MAXCACHE)
498 mopts.malloc_cache = MALLOC_MAXCACHE;
499 break;
500 case '<':
501 mopts.malloc_cache >>= 1;
502 break;
503 case 'a':
504 mopts.malloc_abort = 0;
505 break;
506 case 'A':
507 mopts.malloc_abort = 1;
508 break;
509#ifdef MALLOC_STATS
510 case 'd':
511 mopts.malloc_stats = 0;
512 break;
513 case 'D':
514 mopts.malloc_stats = 1;
515 break;
516#endif /* MALLOC_STATS */
517 case 'f':
518 mopts.malloc_freenow = 0;
519 mopts.malloc_freeunmap = 0;
520 break;
521 case 'F':
522 mopts.malloc_freenow = 1;
523 mopts.malloc_freeunmap = 1;
524 break;
525 case 'g':
526 mopts.malloc_guard = 0;
527 break;
528 case 'G':
529 mopts.malloc_guard = MALLOC_PAGESIZE;
530 break;
531 case 'h':
532 mopts.malloc_hint = 0;
533 break;
534 case 'H':
535 mopts.malloc_hint = 1;
536 break;
537 case 'j':
538 mopts.malloc_junk = 0;
539 break;
540 case 'J':
541 mopts.malloc_junk = 1;
542 break;
543 case 'n':
544 case 'N':
545 break;
546 case 'p':
547 mopts.malloc_move = 0;
548 break;
549 case 'P':
550 mopts.malloc_move = 1;
551 break;
552 case 'r':
553 mopts.malloc_realloc = 0;
554 break;
555 case 'R':
556 mopts.malloc_realloc = 1;
557 break;
558 case 's':
559 mopts.malloc_freeunmap = mopts.malloc_junk = 0;
560 mopts.malloc_guard = 0;
561 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
562 break;
563 case 'S':
564 mopts.malloc_freeunmap = mopts.malloc_junk = 1;
565 mopts.malloc_guard = MALLOC_PAGESIZE;
566 mopts.malloc_cache = 0;
567 break;
568 case 'u':
569 mopts.malloc_freeunmap = 0;
570 break;
571 case 'U':
572 mopts.malloc_freeunmap = 1;
573 break;
574 case 'x':
575 mopts.malloc_xmalloc = 0;
576 break;
577 case 'X':
578 mopts.malloc_xmalloc = 1;
579 break;
580 case 'z':
581 mopts.malloc_zero = 0;
582 break;
583 case 'Z':
584 mopts.malloc_zero = 1;
585 break;
586 default: {
587 static const char q[] = "malloc() warning: "
588 "unknown char in MALLOC_OPTIONS\n";
589 write(STDERR_FILENO, q, sizeof(q) - 1);
590 break;
591 }
592 }
593 }
594 }
595
596 /*
597 * We want junk in the entire allocation, and zero only in the part
598 * the user asked for.
599 */
600 if (mopts.malloc_zero)
601 mopts.malloc_junk = 1;
602
603#ifdef MALLOC_STATS
604 if (mopts.malloc_stats && (atexit(malloc_exit) == -1)) {
605 static const char q[] = "malloc() warning: atexit(2) failed."
606 " Will not be able to dump stats on exit\n";
607 write(STDERR_FILENO, q, sizeof(q) - 1);
608 }
609#endif /* MALLOC_STATS */
610
611 while ((mopts.malloc_canary = arc4random()) == 0)
612 ;
613
614 /*
615 * Allocate dir_info with a guard page on either side. Also
616 * randomise offset inside the page at which the dir_info
617 * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
618 */
619 if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
620 return -1;
621 mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
622 mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
623 MALLOC_PAGESIZE, PROT_NONE);
624 d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
625 d = (struct dir_info *)(p + MALLOC_PAGESIZE +
626 (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
627
628 d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS;
629 regioninfo_size = d->regions_total * sizeof(struct region_info);
630 d->r = MMAP(regioninfo_size);
631 if (d->r == MAP_FAILED) {
632 wrterror("malloc init mmap failed", NULL);
633 d->regions_total = 0;
634 return 1;
635 }
636 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
637 LIST_INIT(&d->chunk_info_list[i]);
638 LIST_INIT(&d->chunk_dir[i]);
639 }
640 malloc_used += regioninfo_size;
641 d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
642 d->canary2 = ~d->canary1;
643
644 *dp = d;
645
646 /*
647 * Options have been set and will never be reset.
648 * Prevent further tampering with them.
649 */
650 if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
651 mprotect(&malloc_readonly, sizeof(malloc_readonly), PROT_READ);
652
653 return 0;
654}
655
656static int
657omalloc_grow(struct dir_info *d)
658{
659 size_t newtotal;
660 size_t newsize;
661 size_t mask;
662 size_t i;
663 struct region_info *p;
664
665 if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 )
666 return 1;
667
668 newtotal = d->regions_total * 2;
669 newsize = newtotal * sizeof(struct region_info);
670 mask = newtotal - 1;
671
672 p = MMAP(newsize);
673 if (p == MAP_FAILED)
674 return 1;
675
676 malloc_used += newsize;
677 memset(p, 0, newsize);
678 STATS_ZERO(d->inserts);
679 STATS_ZERO(d->insert_collisions);
680 for (i = 0; i < d->regions_total; i++) {
681 void *q = d->r[i].p;
682 if (q != NULL) {
683 size_t index = hash(q) & mask;
684 STATS_INC(d->inserts);
685 while (p[index].p != NULL) {
686 index = (index - 1) & mask;
687 STATS_INC(d->insert_collisions);
688 }
689 p[index] = d->r[i];
690 }
691 }
692 /* avoid pages containing meta info to end up in cache */
693 if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
694 wrterror("munmap", d->r);
695 else
696 malloc_used -= d->regions_total * sizeof(struct region_info);
697 d->regions_free = d->regions_free + d->regions_total;
698 d->regions_total = newtotal;
699 d->r = p;
700 return 0;
701}
702
703static struct chunk_info *
704alloc_chunk_info(struct dir_info *d, int bits)
705{
706 struct chunk_info *p;
707 size_t size, count;
708
709 if (bits == 0)
710 count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
711 else
712 count = MALLOC_PAGESIZE >> bits;
713
714 size = howmany(count, MALLOC_BITS);
715 size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
716 size = ALIGN(size);
717
718 if (LIST_EMPTY(&d->chunk_info_list[bits])) {
719 char *q;
720 int i;
721
722 q = MMAP(MALLOC_PAGESIZE);
723 if (q == MAP_FAILED)
724 return NULL;
725 malloc_used += MALLOC_PAGESIZE;
726 count = MALLOC_PAGESIZE / size;
727 for (i = 0; i < count; i++, q += size)
728 LIST_INSERT_HEAD(&d->chunk_info_list[bits],
729 (struct chunk_info *)q, entries);
730 }
731 p = LIST_FIRST(&d->chunk_info_list[bits]);
732 LIST_REMOVE(p, entries);
733 memset(p, 0, size);
734 p->canary = d->canary1;
735 return p;
736}
737
738
739/*
740 * The hashtable uses the assumption that p is never NULL. This holds since
741 * non-MAP_FIXED mappings with hint 0 start at BRKSIZ.
742 */
743static int
744insert(struct dir_info *d, void *p, size_t sz, void *f)
745{
746 size_t index;
747 size_t mask;
748 void *q;
749
750 if (d->regions_free * 4 < d->regions_total) {
751 if (omalloc_grow(d))
752 return 1;
753 }
754 mask = d->regions_total - 1;
755 index = hash(p) & mask;
756 q = d->r[index].p;
757 STATS_INC(d->inserts);
758 while (q != NULL) {
759 index = (index - 1) & mask;
760 q = d->r[index].p;
761 STATS_INC(d->insert_collisions);
762 }
763 d->r[index].p = p;
764 d->r[index].size = sz;
765#ifdef MALLOC_STATS
766 d->r[index].f = f;
767#endif
768 d->regions_free--;
769 return 0;
770}
771
772static struct region_info *
773find(struct dir_info *d, void *p)
774{
775 size_t index;
776 size_t mask = d->regions_total - 1;
777 void *q, *r;
778
779 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
780 d->canary1 != ~d->canary2)
781 wrterror("internal struct corrupt", NULL);
782 p = MASK_POINTER(p);
783 index = hash(p) & mask;
784 r = d->r[index].p;
785 q = MASK_POINTER(r);
786 STATS_INC(d->finds);
787 while (q != p && r != NULL) {
788 index = (index - 1) & mask;
789 r = d->r[index].p;
790 q = MASK_POINTER(r);
791 STATS_INC(d->find_collisions);
792 }
793 return (q == p && r != NULL) ? &d->r[index] : NULL;
794}
795
796static void
797delete(struct dir_info *d, struct region_info *ri)
798{
799 /* algorithm R, Knuth Vol III section 6.4 */
800 size_t mask = d->regions_total - 1;
801 size_t i, j, r;
802
803 if (d->regions_total & (d->regions_total - 1))
804 wrterror("regions_total not 2^x", NULL);
805 d->regions_free++;
806 STATS_INC(g_pool->deletes);
807
808 i = ri - d->r;
809 for (;;) {
810 d->r[i].p = NULL;
811 d->r[i].size = 0;
812 j = i;
813 for (;;) {
814 i = (i - 1) & mask;
815 if (d->r[i].p == NULL)
816 return;
817 r = hash(d->r[i].p) & mask;
818 if ((i <= r && r < j) || (r < j && j < i) ||
819 (j < i && i <= r))
820 continue;
821 d->r[j] = d->r[i];
822 STATS_INC(g_pool->delete_moves);
823 break;
824 }
825
826 }
827}
828
829/*
830 * Allocate a page of chunks
831 */
832static struct chunk_info *
833omalloc_make_chunks(struct dir_info *d, int bits)
834{
835 struct chunk_info *bp;
836 void *pp;
837 int i, k;
838
839 /* Allocate a new bucket */
840 pp = map(d, MALLOC_PAGESIZE, 0);
841 if (pp == MAP_FAILED)
842 return NULL;
843
844 bp = alloc_chunk_info(d, bits);
845 if (bp == NULL) {
846 unmap(d, pp, MALLOC_PAGESIZE);
847 return NULL;
848 }
849
850 /* memory protect the page allocated in the malloc(0) case */
851 if (bits == 0) {
852 bp->size = 0;
853 bp->shift = 1;
854 i = MALLOC_MINSIZE - 1;
855 while (i >>= 1)
856 bp->shift++;
857 bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
858 bp->page = pp;
859
860 k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
861 if (k < 0) {
862 unmap(d, pp, MALLOC_PAGESIZE);
863 LIST_INSERT_HEAD(&d->chunk_info_list[0], bp, entries);
864 return NULL;
865 }
866 } else {
867 bp->size = 1U << bits;
868 bp->shift = bits;
869 bp->total = bp->free = MALLOC_PAGESIZE >> bits;
870 bp->page = pp;
871 }
872
873 /* set all valid bits in the bitmap */
874 k = bp->total;
875 i = 0;
876
877 /* Do a bunch at a time */
878 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
879 bp->bits[i / MALLOC_BITS] = (u_short)~0U;
880
881 for (; i < k; i++)
882 bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS);
883
884 LIST_INSERT_HEAD(&d->chunk_dir[bits], bp, entries);
885
886 bits++;
887 if ((uintptr_t)pp & bits)
888 wrterror("pp & bits", pp);
889
890 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
891 return bp;
892}
893
894
895/*
896 * Allocate a chunk
897 */
898static void *
899malloc_bytes(struct dir_info *d, size_t size, void *f)
900{
901 int i, j;
902 size_t k;
903 u_short u, *lp;
904 struct chunk_info *bp;
905
906 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
907 d->canary1 != ~d->canary2)
908 wrterror("internal struct corrupt", NULL);
909 /* Don't bother with anything less than this */
910 /* unless we have a malloc(0) requests */
911 if (size != 0 && size < MALLOC_MINSIZE)
912 size = MALLOC_MINSIZE;
913
914 /* Find the right bucket */
915 if (size == 0)
916 j = 0;
917 else {
918 j = MALLOC_MINSHIFT;
919 i = (size - 1) >> (MALLOC_MINSHIFT - 1);
920 while (i >>= 1)
921 j++;
922 }
923
924 /* If it's empty, make a page more of that size chunks */
925 if (LIST_EMPTY(&d->chunk_dir[j])) {
926 bp = omalloc_make_chunks(d, j);
927 if (bp == NULL)
928 return NULL;
929 } else
930 bp = LIST_FIRST(&d->chunk_dir[j]);
931
932 if (bp->canary != d->canary1)
933 wrterror("chunk info corrupted", NULL);
934
935 i = d->chunk_start;
936 if (bp->free > 1)
937 i += getrnibble();
938 if (i >= bp->total)
939 i &= bp->total - 1;
940 for (;;) {
941 for (;;) {
942 lp = &bp->bits[i / MALLOC_BITS];
943 if (!*lp) {
944 i += MALLOC_BITS;
945 i &= ~(MALLOC_BITS - 1);
946 if (i >= bp->total)
947 i = 0;
948 } else
949 break;
950 }
951 k = i % MALLOC_BITS;
952 u = 1 << k;
953 if (*lp & u)
954 break;
955 if (++i >= bp->total)
956 i = 0;
957 }
958 d->chunk_start += i + 1;
959#ifdef MALLOC_STATS
960 if (i == 0) {
961 struct region_info *r = find(d, bp->page);
962 r->f = f;
963 }
964#endif
965
966 *lp ^= u;
967
968 /* If there are no more free, remove from free-list */
969 if (!--bp->free)
970 LIST_REMOVE(bp, entries);
971
972 /* Adjust to the real offset of that chunk */
973 k += (lp - bp->bits) * MALLOC_BITS;
974 k <<= bp->shift;
975
976 if (mopts.malloc_junk && bp->size > 0)
977 memset((char *)bp->page + k, SOME_JUNK, bp->size);
978 return ((char *)bp->page + k);
979}
980
981
982/*
983 * Free a chunk, and possibly the page it's on, if the page becomes empty.
984 */
985static void
986free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
987{
988 struct chunk_head *mp;
989 struct chunk_info *info;
990 int i;
991
992 info = (struct chunk_info *)r->size;
993 if (info->canary != d->canary1)
994 wrterror("chunk info corrupted", NULL);
995
996 /* Find the chunk number on the page */
997 i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
998
999 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) {
1000 wrterror("modified chunk-pointer", ptr);
1001 return;
1002 }
1003 if (info->bits[i / MALLOC_BITS] & (1U << (i % MALLOC_BITS))) {
1004 wrterror("chunk is already free", ptr);
1005 return;
1006 }
1007
1008 info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS);
1009 info->free++;
1010
1011 if (info->size != 0)
1012 mp = d->chunk_dir + info->shift;
1013 else
1014 mp = d->chunk_dir;
1015
1016 if (info->free == 1) {
1017 /* Page became non-full */
1018 LIST_INSERT_HEAD(mp, info, entries);
1019 return;
1020 }
1021 if (info->free != info->total)
1022 return;
1023
1024 LIST_REMOVE(info, entries);
1025
1026 if (info->size == 0 && !mopts.malloc_freeunmap)
1027 mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
1028 unmap(d, info->page, MALLOC_PAGESIZE);
1029
1030 delete(d, r);
1031 if (info->size != 0)
1032 mp = &d->chunk_info_list[info->shift];
1033 else
1034 mp = &d->chunk_info_list[0];
1035 LIST_INSERT_HEAD(mp, info, entries);
1036}
1037
1038
1039
1040static void *
1041omalloc(size_t sz, int zero_fill, void *f)
1042{
1043 void *p;
1044 size_t psz;
1045
1046 if (sz > MALLOC_MAXCHUNK) {
1047 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1048 errno = ENOMEM;
1049 return NULL;
1050 }
1051 sz += mopts.malloc_guard;
1052 psz = PAGEROUND(sz);
1053 p = map(g_pool, psz, zero_fill);
1054 if (p == MAP_FAILED) {
1055 errno = ENOMEM;
1056 return NULL;
1057 }
1058 if (insert(g_pool, p, sz, f)) {
1059 unmap(g_pool, p, psz);
1060 errno = ENOMEM;
1061 return NULL;
1062 }
1063 if (mopts.malloc_guard) {
1064 if (mprotect((char *)p + psz - mopts.malloc_guard,
1065 mopts.malloc_guard, PROT_NONE))
1066 wrterror("mprotect", NULL);
1067 malloc_guarded += mopts.malloc_guard;
1068 }
1069
1070 if (mopts.malloc_move &&
1071 sz - mopts.malloc_guard < MALLOC_PAGESIZE -
1072 MALLOC_LEEWAY) {
1073 /* fill whole allocation */
1074 if (mopts.malloc_junk)
1075 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1076 /* shift towards the end */
1077 p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_LEEWAY -
1078 (sz - mopts.malloc_guard)) & ~(MALLOC_MINSIZE-1));
1079 /* fill zeros if needed and overwritten above */
1080 if (zero_fill && mopts.malloc_junk)
1081 memset(p, 0, sz - mopts.malloc_guard);
1082 } else {
1083 if (mopts.malloc_junk) {
1084 if (zero_fill)
1085 memset((char *)p + sz - mopts.malloc_guard,
1086 SOME_JUNK, psz - sz);
1087 else
1088 memset(p, SOME_JUNK,
1089 psz - mopts.malloc_guard);
1090 }
1091 }
1092
1093 } else {
1094 /* takes care of SOME_JUNK */
1095 p = malloc_bytes(g_pool, sz, f);
1096 if (zero_fill && p != NULL && sz > 0)
1097 memset(p, 0, sz);
1098 }
1099
1100 return p;
1101}
1102
1103/*
1104 * Common function for handling recursion. Only
1105 * print the error message once, to avoid making the problem
1106 * potentially worse.
1107 */
1108static void
1109malloc_recurse(void)
1110{
1111 static int noprint;
1112
1113 if (noprint == 0) {
1114 noprint = 1;
1115 wrterror("recursive call", NULL);
1116 }
1117 malloc_active--;
1118 _MALLOC_UNLOCK();
1119 errno = EDEADLK;
1120}
1121
1122static int
1123malloc_init(void)
1124{
1125 if (omalloc_init(&g_pool)) {
1126 _MALLOC_UNLOCK();
1127 if (mopts.malloc_xmalloc)
1128 wrterror("out of memory", NULL);
1129 errno = ENOMEM;
1130 return -1;
1131 }
1132 return 0;
1133}
1134
1135void *
1136malloc(size_t size)
1137{
1138 void *r;
1139 int saved_errno = errno;
1140
1141 _MALLOC_LOCK();
1142 malloc_func = " in malloc():";
1143 if (g_pool == NULL) {
1144 if (malloc_init() != 0)
1145 return NULL;
1146 }
1147 if (malloc_active++) {
1148 malloc_recurse();
1149 return NULL;
1150 }
1151 r = omalloc(size, mopts.malloc_zero, CALLER);
1152 malloc_active--;
1153 _MALLOC_UNLOCK();
1154 if (r == NULL && mopts.malloc_xmalloc) {
1155 wrterror("out of memory", NULL);
1156 errno = ENOMEM;
1157 }
1158 if (r != NULL)
1159 errno = saved_errno;
1160 return r;
1161}
1162
1163static void
1164ofree(void *p)
1165{
1166 struct region_info *r;
1167 size_t sz;
1168
1169 r = find(g_pool, p);
1170 if (r == NULL) {
1171 wrterror("bogus pointer (double free?)", p);
1172 return;
1173 }
1174 REALSIZE(sz, r);
1175 if (sz > MALLOC_MAXCHUNK) {
1176 if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
1177 MALLOC_LEEWAY) {
1178 if (r->p != p) {
1179 wrterror("bogus pointer", p);
1180 return;
1181 }
1182 } else {
1183#if notyetbecause_of_realloc
1184 /* shifted towards the end */
1185 if (p != ((char *)r->p) + ((MALLOC_PAGESIZE -
1186 MALLOC_MINSIZE - sz - mopts.malloc_guard) &
1187 ~(MALLOC_MINSIZE-1))) {
1188 }
1189#endif
1190 p = r->p;
1191 }
1192 if (mopts.malloc_guard) {
1193 if (sz < mopts.malloc_guard)
1194 wrterror("guard size", NULL);
1195 if (!mopts.malloc_freeunmap) {
1196 if (mprotect((char *)p + PAGEROUND(sz) -
1197 mopts.malloc_guard, mopts.malloc_guard,
1198 PROT_READ | PROT_WRITE))
1199 wrterror("mprotect", NULL);
1200 }
1201 malloc_guarded -= mopts.malloc_guard;
1202 }
1203 if (mopts.malloc_junk && !mopts.malloc_freeunmap)
1204 memset(p, SOME_FREEJUNK,
1205 PAGEROUND(sz) - mopts.malloc_guard);
1206 unmap(g_pool, p, PAGEROUND(sz));
1207 delete(g_pool, r);
1208 } else {
1209 void *tmp;
1210 int i;
1211
1212 if (mopts.malloc_junk && sz > 0)
1213 memset(p, SOME_FREEJUNK, sz);
1214 if (!mopts.malloc_freenow) {
1215 i = getrnibble();
1216 tmp = p;
1217 p = g_pool->delayed_chunks[i];
1218 g_pool->delayed_chunks[i] = tmp;
1219 }
1220 if (p != NULL) {
1221 r = find(g_pool, p);
1222 if (r == NULL) {
1223 wrterror("bogus pointer (double free?)", p);
1224 return;
1225 }
1226 free_bytes(g_pool, r, p);
1227 }
1228 }
1229}
1230
1231void
1232free(void *ptr)
1233{
1234 int saved_errno = errno;
1235
1236 /* This is legal. */
1237 if (ptr == NULL)
1238 return;
1239
1240 _MALLOC_LOCK();
1241 malloc_func = " in free():";
1242 if (g_pool == NULL) {
1243 _MALLOC_UNLOCK();
1244 wrterror("free() called before allocation", NULL);
1245 return;
1246 }
1247 if (malloc_active++) {
1248 malloc_recurse();
1249 return;
1250 }
1251 ofree(ptr);
1252 malloc_active--;
1253 _MALLOC_UNLOCK();
1254 errno = saved_errno;
1255}
1256
1257
1258static void *
1259orealloc(void *p, size_t newsz, void *f)
1260{
1261 struct region_info *r;
1262 size_t oldsz, goldsz, gnewsz;
1263 void *q;
1264
1265 if (p == NULL)
1266 return omalloc(newsz, 0, f);
1267
1268 r = find(g_pool, p);
1269 if (r == NULL) {
1270 wrterror("bogus pointer (double free?)", p);
1271 return NULL;
1272 }
1273 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1274 errno = ENOMEM;
1275 return NULL;
1276 }
1277
1278 REALSIZE(oldsz, r);
1279 goldsz = oldsz;
1280 if (oldsz > MALLOC_MAXCHUNK) {
1281 if (oldsz < mopts.malloc_guard)
1282 wrterror("guard size", NULL);
1283 oldsz -= mopts.malloc_guard;
1284 }
1285
1286 gnewsz = newsz;
1287 if (gnewsz > MALLOC_MAXCHUNK)
1288 gnewsz += mopts.malloc_guard;
1289
1290 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
1291 !mopts.malloc_realloc) {
1292 size_t roldsz = PAGEROUND(goldsz);
1293 size_t rnewsz = PAGEROUND(gnewsz);
1294
1295 if (rnewsz > roldsz) {
1296 if (!mopts.malloc_guard) {
1297 void *hint = (char *)p + roldsz;
1298 size_t needed = rnewsz - roldsz;
1299
1300 STATS_INC(g_pool->cheap_realloc_tries);
1301 zapcacheregion(g_pool, hint, needed);
1302 q = MQUERY(hint, needed);
1303 if (q == hint)
1304 q = MMAPA(hint, needed);
1305 else
1306 q = MAP_FAILED;
1307 if (q == hint) {
1308 malloc_used += needed;
1309 if (mopts.malloc_junk)
1310 memset(q, SOME_JUNK, needed);
1311 r->size = newsz;
1312 STATS_SETF(r, f);
1313 STATS_INC(g_pool->cheap_reallocs);
1314 return p;
1315 } else if (q != MAP_FAILED) {
1316 if (munmap(q, needed))
1317 wrterror("munmap", q);
1318 }
1319 }
1320 } else if (rnewsz < roldsz) {
1321 if (mopts.malloc_guard) {
1322 if (mprotect((char *)p + roldsz -
1323 mopts.malloc_guard, mopts.malloc_guard,
1324 PROT_READ | PROT_WRITE))
1325 wrterror("mprotect", NULL);
1326 if (mprotect((char *)p + rnewsz -
1327 mopts.malloc_guard, mopts.malloc_guard,
1328 PROT_NONE))
1329 wrterror("mprotect", NULL);
1330 }
1331 unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz);
1332 r->size = gnewsz;
1333 STATS_SETF(r, f);
1334 return p;
1335 } else {
1336 if (newsz > oldsz && mopts.malloc_junk)
1337 memset((char *)p + newsz, SOME_JUNK,
1338 rnewsz - mopts.malloc_guard - newsz);
1339 r->size = gnewsz;
1340 STATS_SETF(r, f);
1341 return p;
1342 }
1343 }
1344 if (newsz <= oldsz && newsz > oldsz / 2 && !mopts.malloc_realloc) {
1345 if (mopts.malloc_junk && newsz > 0)
1346 memset((char *)p + newsz, SOME_JUNK, oldsz - newsz);
1347 STATS_SETF(r, f);
1348 return p;
1349 } else if (newsz != oldsz || mopts.malloc_realloc) {
1350 q = omalloc(newsz, 0, f);
1351 if (q == NULL)
1352 return NULL;
1353 if (newsz != 0 && oldsz != 0)
1354 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1355 ofree(p);
1356 return q;
1357 } else {
1358 STATS_SETF(r, f);
1359 return p;
1360 }
1361}
1362
1363void *
1364realloc(void *ptr, size_t size)
1365{
1366 void *r;
1367 int saved_errno = errno;
1368
1369 _MALLOC_LOCK();
1370 malloc_func = " in realloc():";
1371 if (g_pool == NULL) {
1372 if (malloc_init() != 0)
1373 return NULL;
1374 }
1375 if (malloc_active++) {
1376 malloc_recurse();
1377 return NULL;
1378 }
1379 r = orealloc(ptr, size, CALLER);
1380
1381 malloc_active--;
1382 _MALLOC_UNLOCK();
1383 if (r == NULL && mopts.malloc_xmalloc) {
1384 wrterror("out of memory", NULL);
1385 errno = ENOMEM;
1386 }
1387 if (r != NULL)
1388 errno = saved_errno;
1389 return r;
1390}
1391
1392
1393#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
1394
1395void *
1396calloc(size_t nmemb, size_t size)
1397{
1398 void *r;
1399 int saved_errno = errno;
1400
1401 _MALLOC_LOCK();
1402 malloc_func = " in calloc():";
1403 if (g_pool == NULL) {
1404 if (malloc_init() != 0)
1405 return NULL;
1406 }
1407 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1408 nmemb > 0 && SIZE_MAX / nmemb < size) {
1409 _MALLOC_UNLOCK();
1410 if (mopts.malloc_xmalloc)
1411 wrterror("out of memory", NULL);
1412 errno = ENOMEM;
1413 return NULL;
1414 }
1415
1416 if (malloc_active++) {
1417 malloc_recurse();
1418 return NULL;
1419 }
1420
1421 size *= nmemb;
1422 r = omalloc(size, 1, CALLER);
1423
1424 malloc_active--;
1425 _MALLOC_UNLOCK();
1426 if (r == NULL && mopts.malloc_xmalloc) {
1427 wrterror("out of memory", NULL);
1428 errno = ENOMEM;
1429 }
1430 if (r != NULL)
1431 errno = saved_errno;
1432 return r;
1433}
1434
1435static void *
1436mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
1437{
1438 char *p, *q;
1439
1440 if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) {
1441 wrterror("mapalign bad alignment", NULL);
1442 return MAP_FAILED;
1443 }
1444 if (sz != PAGEROUND(sz)) {
1445 wrterror("mapalign round", NULL);
1446 return MAP_FAILED;
1447 }
1448
1449 /* Allocate sz + alignment bytes of memory, which must include a
1450 * subrange of size bytes that is properly aligned. Unmap the
1451 * other bytes, and then return that subrange.
1452 */
1453
1454 /* We need sz + alignment to fit into a size_t. */
1455 if (alignment > SIZE_MAX - sz)
1456 return MAP_FAILED;
1457
1458 p = map(d, sz + alignment, zero_fill);
1459 if (p == MAP_FAILED)
1460 return MAP_FAILED;
1461 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
1462 if (q != p) {
1463 if (munmap(p, q - p))
1464 wrterror("munmap", p);
1465 }
1466 if (munmap(q + sz, alignment - (q - p)))
1467 wrterror("munmap", q + sz);
1468 malloc_used -= alignment;
1469
1470 return q;
1471}
1472
1473static void *
1474omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
1475{
1476 size_t psz;
1477 void *p;
1478
1479 if (alignment <= MALLOC_PAGESIZE) {
1480 /*
1481 * max(size, alignment) is enough to assure the requested alignment,
1482 * since the allocator always allocates power-of-two blocks.
1483 */
1484 if (sz < alignment)
1485 sz = alignment;
1486 return omalloc(sz, zero_fill, f);
1487 }
1488
1489 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1490 errno = ENOMEM;
1491 return NULL;
1492 }
1493
1494 sz += mopts.malloc_guard;
1495 psz = PAGEROUND(sz);
1496
1497 p = mapalign(g_pool, alignment, psz, zero_fill);
1498 if (p == NULL) {
1499 errno = ENOMEM;
1500 return NULL;
1501 }
1502
1503 if (insert(g_pool, p, sz, f)) {
1504 unmap(g_pool, p, psz);
1505 errno = ENOMEM;
1506 return NULL;
1507 }
1508
1509 if (mopts.malloc_guard) {
1510 if (mprotect((char *)p + psz - mopts.malloc_guard,
1511 mopts.malloc_guard, PROT_NONE))
1512 wrterror("mprotect", NULL);
1513 malloc_guarded += mopts.malloc_guard;
1514 }
1515
1516 if (mopts.malloc_junk) {
1517 if (zero_fill)
1518 memset((char *)p + sz - mopts.malloc_guard,
1519 SOME_JUNK, psz - sz);
1520 else
1521 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1522 }
1523
1524 return p;
1525}
1526
1527int
1528posix_memalign(void **memptr, size_t alignment, size_t size)
1529{
1530 int res, saved_errno = errno;
1531 void *r;
1532
1533 /* Make sure that alignment is a large enough power of 2. */
1534 if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *))
1535 return EINVAL;
1536
1537 _MALLOC_LOCK();
1538 malloc_func = " in posix_memalign():";
1539 if (g_pool == NULL) {
1540 if (malloc_init() != 0)
1541 goto err;
1542 }
1543 if (malloc_active++) {
1544 malloc_recurse();
1545 goto err;
1546 }
1547 r = omemalign(alignment, size, mopts.malloc_zero, CALLER);
1548 malloc_active--;
1549 _MALLOC_UNLOCK();
1550 if (r == NULL) {
1551 if (mopts.malloc_xmalloc) {
1552 wrterror("out of memory", NULL);
1553 errno = ENOMEM;
1554 }
1555 goto err;
1556 }
1557 errno = saved_errno;
1558 *memptr = r;
1559 return 0;
1560
1561err:
1562 res = errno;
1563 errno = saved_errno;
1564 return res;
1565}
1566
1567#ifdef MALLOC_STATS
1568
1569struct malloc_leak {
1570 void (*f)();
1571 size_t total_size;
1572 int count;
1573};
1574
1575struct leaknode {
1576 RB_ENTRY(leaknode) entry;
1577 struct malloc_leak d;
1578};
1579
1580static int
1581leakcmp(struct leaknode *e1, struct leaknode *e2)
1582{
1583 return e1->d.f < e2->d.f ? -1 : e1->d.f > e2->d.f;
1584}
1585
1586static RB_HEAD(leaktree, leaknode) leakhead;
1587RB_GENERATE_STATIC(leaktree, leaknode, entry, leakcmp)
1588
1589static void
1590putleakinfo(void *f, size_t sz, int cnt)
1591{
1592 struct leaknode key, *p;
1593 static struct leaknode *page;
1594 static int used;
1595
1596 if (cnt == 0)
1597 return;
1598
1599 key.d.f = f;
1600 p = RB_FIND(leaktree, &leakhead, &key);
1601 if (p == NULL) {
1602 if (page == NULL ||
1603 used >= MALLOC_PAGESIZE / sizeof(struct leaknode)) {
1604 page = MMAP(MALLOC_PAGESIZE);
1605 if (page == MAP_FAILED)
1606 return;
1607 used = 0;
1608 }
1609 p = &page[used++];
1610 p->d.f = f;
1611 p->d.total_size = sz * cnt;
1612 p->d.count = cnt;
1613 RB_INSERT(leaktree, &leakhead, p);
1614 } else {
1615 p->d.total_size += sz * cnt;
1616 p->d.count += cnt;
1617 }
1618}
1619
1620static struct malloc_leak *malloc_leaks;
1621
1622static void
1623dump_leaks(int fd)
1624{
1625 struct leaknode *p;
1626 char buf[64];
1627 int i = 0;
1628
1629 snprintf(buf, sizeof(buf), "Leak report\n");
1630 write(fd, buf, strlen(buf));
1631 snprintf(buf, sizeof(buf), " f sum # avg\n");
1632 write(fd, buf, strlen(buf));
1633 /* XXX only one page of summary */
1634 if (malloc_leaks == NULL)
1635 malloc_leaks = MMAP(MALLOC_PAGESIZE);
1636 if (malloc_leaks != MAP_FAILED)
1637 memset(malloc_leaks, 0, MALLOC_PAGESIZE);
1638 RB_FOREACH(p, leaktree, &leakhead) {
1639 snprintf(buf, sizeof(buf), "%12p %7zu %6u %6zu\n", p->d.f,
1640 p->d.total_size, p->d.count, p->d.total_size / p->d.count);
1641 write(fd, buf, strlen(buf));
1642 if (malloc_leaks == MAP_FAILED ||
1643 i >= MALLOC_PAGESIZE / sizeof(struct malloc_leak))
1644 continue;
1645 malloc_leaks[i].f = p->d.f;
1646 malloc_leaks[i].total_size = p->d.total_size;
1647 malloc_leaks[i].count = p->d.count;
1648 i++;
1649 }
1650}
1651
1652static void
1653dump_chunk(int fd, struct chunk_info *p, void *f, int fromfreelist)
1654{
1655 char buf[64];
1656
1657 while (p != NULL) {
1658 snprintf(buf, sizeof(buf), "chunk %12p %12p %4d %d/%d\n",
1659 p->page, ((p->bits[0] & 1) ? NULL : f),
1660 p->size, p->free, p->total);
1661 write(fd, buf, strlen(buf));
1662 if (!fromfreelist) {
1663 if (p->bits[0] & 1)
1664 putleakinfo(NULL, p->size, p->total - p->free);
1665 else {
1666 putleakinfo(f, p->size, 1);
1667 putleakinfo(NULL, p->size,
1668 p->total - p->free - 1);
1669 }
1670 break;
1671 }
1672 p = LIST_NEXT(p, entries);
1673 if (p != NULL) {
1674 snprintf(buf, sizeof(buf), " ");
1675 write(fd, buf, strlen(buf));
1676 }
1677 }
1678}
1679
1680static void
1681dump_free_chunk_info(int fd, struct dir_info *d)
1682{
1683 char buf[64];
1684 int i, count;
1685
1686 snprintf(buf, sizeof(buf), "Free chunk structs:\n");
1687 write(fd, buf, strlen(buf));
1688 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
1689 struct chunk_info *p;
1690
1691 count = 0;
1692 LIST_FOREACH(p, &d->chunk_info_list[i], entries)
1693 count++;
1694 p = LIST_FIRST(&d->chunk_dir[i]);
1695 if (p == NULL && count == 0)
1696 continue;
1697 snprintf(buf, sizeof(buf), "%2d) %3d ", i, count);
1698 write(fd, buf, strlen(buf));
1699 if (p != NULL)
1700 dump_chunk(fd, p, NULL, 1);
1701 else
1702 write(fd, "\n", 1);
1703 }
1704
1705}
1706
1707static void
1708dump_free_page_info(int fd, struct dir_info *d)
1709{
1710 char buf[64];
1711 int i;
1712
1713 snprintf(buf, sizeof(buf), "Free pages cached: %zu\n",
1714 d->free_regions_size);
1715 write(fd, buf, strlen(buf));
1716 for (i = 0; i < mopts.malloc_cache; i++) {
1717 if (d->free_regions[i].p != NULL) {
1718 snprintf(buf, sizeof(buf), "%2d) ", i);
1719 write(fd, buf, strlen(buf));
1720 snprintf(buf, sizeof(buf), "free at %p: %zu\n",
1721 d->free_regions[i].p, d->free_regions[i].size);
1722 write(fd, buf, strlen(buf));
1723 }
1724 }
1725}
1726
1727static void
1728malloc_dump1(int fd, struct dir_info *d)
1729{
1730 char buf[64];
1731 size_t i, realsize;
1732
1733 snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d);
1734 write(fd, buf, strlen(buf));
1735 if (d == NULL)
1736 return;
1737 snprintf(buf, sizeof(buf), "Region slots free %zu/%zu\n",
1738 d->regions_free, d->regions_total);
1739 write(fd, buf, strlen(buf));
1740 snprintf(buf, sizeof(buf), "Finds %zu/%zu\n", d->finds,
1741 d->find_collisions);
1742 write(fd, buf, strlen(buf));
1743 snprintf(buf, sizeof(buf), "Inserts %zu/%zu\n", d->inserts,
1744 d->insert_collisions);
1745 write(fd, buf, strlen(buf));
1746 snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes,
1747 d->delete_moves);
1748 write(fd, buf, strlen(buf));
1749 snprintf(buf, sizeof(buf), "Cheap reallocs %zu/%zu\n",
1750 d->cheap_reallocs, d->cheap_realloc_tries);
1751 write(fd, buf, strlen(buf));
1752 dump_free_chunk_info(fd, d);
1753 dump_free_page_info(fd, d);
1754 snprintf(buf, sizeof(buf),
1755 "slot) hash d type page f size [free/n]\n");
1756 write(fd, buf, strlen(buf));
1757 for (i = 0; i < d->regions_total; i++) {
1758 if (d->r[i].p != NULL) {
1759 size_t h = hash(d->r[i].p) &
1760 (d->regions_total - 1);
1761 snprintf(buf, sizeof(buf), "%4zx) #%4zx %zd ",
1762 i, h, h - i);
1763 write(fd, buf, strlen(buf));
1764 REALSIZE(realsize, &d->r[i]);
1765 if (realsize > MALLOC_MAXCHUNK) {
1766 putleakinfo(d->r[i].f, realsize, 1);
1767 snprintf(buf, sizeof(buf),
1768 "pages %12p %12p %zu\n", d->r[i].p,
1769 d->r[i].f, realsize);
1770 write(fd, buf, strlen(buf));
1771 } else
1772 dump_chunk(fd,
1773 (struct chunk_info *)d->r[i].size,
1774 d->r[i].f, 0);
1775 }
1776 }
1777 snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used);
1778 write(fd, buf, strlen(buf));
1779 snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded);
1780 write(fd, buf, strlen(buf));
1781 dump_leaks(fd);
1782 write(fd, "\n", 1);
1783}
1784
1785void
1786malloc_dump(int fd)
1787{
1788 int i;
1789 void *p;
1790 struct region_info *r;
1791 int saved_errno = errno;
1792
1793 for (i = 0; i <= MALLOC_DELAYED_CHUNKS; i++) {
1794 p = g_pool->delayed_chunks[i];
1795 if (p == NULL)
1796 continue;
1797 r = find(g_pool, p);
1798 if (r == NULL)
1799 wrterror("bogus pointer in malloc_dump", p);
1800 free_bytes(g_pool, r, p);
1801 g_pool->delayed_chunks[i] = NULL;
1802 }
1803 /* XXX leak when run multiple times */
1804 RB_INIT(&leakhead);
1805 malloc_dump1(fd, g_pool);
1806 errno = saved_errno;
1807}
1808
1809static void
1810malloc_exit(void)
1811{
1812 static const char q[] = "malloc() warning: Couldn't dump stats\n";
1813 int save_errno = errno, fd;
1814
1815 fd = open("malloc.out", O_RDWR|O_APPEND);
1816 if (fd != -1) {
1817 malloc_dump(fd);
1818 close(fd);
1819 } else
1820 write(STDERR_FILENO, q, sizeof(q) - 1);
1821 errno = save_errno;
1822}
1823
1824#endif /* MALLOC_STATS */
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000000..43ef8b08e2
--- /dev/null
+++ b/src/lib/libc/stdlib/merge.c
@@ -0,0 +1,333 @@
1/* $OpenBSD: merge.c,v 1.9 2011/03/06 00:55:38 deraadt Exp $ */
2/*-
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Peter McIlroy.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * Hybrid exponential search/linear search merge sort with hybrid
36 * natural/pairwise first pass. Requires about .3% more comparisons
37 * for random data than LSMS with pairwise first pass alone.
38 * It works for objects as small as two bytes.
39 */
40
41#define NATURAL
42#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
43
44/* #define NATURAL to get hybrid natural merge.
45 * (The default is pairwise merging.)
46 */
47
48#include <sys/types.h>
49
50#include <errno.h>
51#include <stdlib.h>
52#include <string.h>
53
54static void setup(u_char *, u_char *, size_t, size_t, int (*)());
55static void insertionsort(u_char *, size_t, size_t, int (*)());
56
57#define ISIZE sizeof(int)
58#define PSIZE sizeof(u_char *)
59#define ICOPY_LIST(src, dst, last) \
60 do \
61 *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
62 while(src < last)
63#define ICOPY_ELT(src, dst, i) \
64 do \
65 *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
66 while (i -= ISIZE)
67
68#define CCOPY_LIST(src, dst, last) \
69 do \
70 *dst++ = *src++; \
71 while (src < last)
72#define CCOPY_ELT(src, dst, i) \
73 do \
74 *dst++ = *src++; \
75 while (i -= 1)
76
77/*
78 * Find the next possible pointer head. (Trickery for forcing an array
79 * to do double duty as a linked list when objects do not align with word
80 * boundaries.
81 */
82/* Assumption: PSIZE is a power of 2. */
83#define EVAL(p) (u_char **) \
84 ((u_char *)0 + \
85 (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
86
87/*
88 * Arguments are as for qsort.
89 */
90int
91mergesort(void *base, size_t nmemb, size_t size,
92 int (*cmp)(const void *, const void *))
93{
94 int i, sense;
95 int big, iflag;
96 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
97 u_char *list2, *list1, *p2, *p, *last, **p1;
98
99 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
100 errno = EINVAL;
101 return (-1);
102 }
103
104 /*
105 * XXX
106 * Stupid subtraction for the Cray.
107 */
108 iflag = 0;
109 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
110 iflag = 1;
111
112 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
113 return (-1);
114
115 list1 = base;
116 setup(list1, list2, nmemb, size, cmp);
117 last = list2 + nmemb * size;
118 i = big = 0;
119 while (*EVAL(list2) != last) {
120 l2 = list1;
121 p1 = EVAL(list1);
122 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
123 p2 = *EVAL(p2);
124 f1 = l2;
125 f2 = l1 = list1 + (p2 - list2);
126 if (p2 != last)
127 p2 = *EVAL(p2);
128 l2 = list1 + (p2 - list2);
129 while (f1 < l1 && f2 < l2) {
130 if ((*cmp)(f1, f2) <= 0) {
131 q = f2;
132 b = f1, t = l1;
133 sense = -1;
134 } else {
135 q = f1;
136 b = f2, t = l2;
137 sense = 0;
138 }
139 if (!big) { /* here i = 0 */
140 while ((b += size) < t && cmp(q, b) >sense)
141 if (++i == 6) {
142 big = 1;
143 goto EXPONENTIAL;
144 }
145 } else {
146EXPONENTIAL: for (i = size; ; i <<= 1)
147 if ((p = (b + i)) >= t) {
148 if ((p = t - size) > b &&
149 (*cmp)(q, p) <= sense)
150 t = p;
151 else
152 b = p;
153 break;
154 } else if ((*cmp)(q, p) <= sense) {
155 t = p;
156 if (i == size)
157 big = 0;
158 goto FASTCASE;
159 } else
160 b = p;
161 while (t > b+size) {
162 i = (((t - b) / size) >> 1) * size;
163 if ((*cmp)(q, p = b + i) <= sense)
164 t = p;
165 else
166 b = p;
167 }
168 goto COPY;
169FASTCASE: while (i > size)
170 if ((*cmp)(q,
171 p = b + (i >>= 1)) <= sense)
172 t = p;
173 else
174 b = p;
175COPY: b = t;
176 }
177 i = size;
178 if (q == f1) {
179 if (iflag) {
180 ICOPY_LIST(f2, tp2, b);
181 ICOPY_ELT(f1, tp2, i);
182 } else {
183 CCOPY_LIST(f2, tp2, b);
184 CCOPY_ELT(f1, tp2, i);
185 }
186 } else {
187 if (iflag) {
188 ICOPY_LIST(f1, tp2, b);
189 ICOPY_ELT(f2, tp2, i);
190 } else {
191 CCOPY_LIST(f1, tp2, b);
192 CCOPY_ELT(f2, tp2, i);
193 }
194 }
195 }
196 if (f2 < l2) {
197 if (iflag)
198 ICOPY_LIST(f2, tp2, l2);
199 else
200 CCOPY_LIST(f2, tp2, l2);
201 } else if (f1 < l1) {
202 if (iflag)
203 ICOPY_LIST(f1, tp2, l1);
204 else
205 CCOPY_LIST(f1, tp2, l1);
206 }
207 *p1 = l2;
208 }
209 tp2 = list1; /* swap list1, list2 */
210 list1 = list2;
211 list2 = tp2;
212 last = list2 + nmemb*size;
213 }
214 if (base == list2) {
215 memmove(list2, list1, nmemb*size);
216 list2 = list1;
217 }
218 free(list2);
219 return (0);
220}
221
222#define swap(a, b) { \
223 s = b; \
224 i = size; \
225 do { \
226 tmp = *a; *a++ = *s; *s++ = tmp; \
227 } while (--i); \
228 a -= size; \
229 }
230#define reverse(bot, top) { \
231 s = top; \
232 do { \
233 i = size; \
234 do { \
235 tmp = *bot; *bot++ = *s; *s++ = tmp; \
236 } while (--i); \
237 s -= size2; \
238 } while(bot < s); \
239}
240
241/*
242 * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
243 * increasing order, list2 in a corresponding linked list. Checks for runs
244 * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
245 * is defined. Otherwise simple pairwise merging is used.)
246 */
247void
248setup(u_char *list1, u_char *list2, size_t n, size_t size,
249 int (*cmp)(const void *, const void *))
250{
251 int i, length, size2, sense;
252 u_char tmp, *f1, *f2, *s, *l2, *last, *p2;
253
254 size2 = size*2;
255 if (n <= 5) {
256 insertionsort(list1, n, size, cmp);
257 *EVAL(list2) = (u_char*) list2 + n*size;
258 return;
259 }
260 /*
261 * Avoid running pointers out of bounds; limit n to evens
262 * for simplicity.
263 */
264 i = 4 + (n & 1);
265 insertionsort(list1 + (n - i) * size, i, size, cmp);
266 last = list1 + size * (n - i);
267 *EVAL(list2 + (last - list1)) = list2 + n * size;
268
269#ifdef NATURAL
270 p2 = list2;
271 f1 = list1;
272 sense = (cmp(f1, f1 + size) > 0);
273 for (; f1 < last; sense = !sense) {
274 length = 2;
275 /* Find pairs with same sense. */
276 for (f2 = f1 + size2; f2 < last; f2 += size2) {
277 if ((cmp(f2, f2+ size) > 0) != sense)
278 break;
279 length += 2;
280 }
281 if (length < THRESHOLD) { /* Pairwise merge */
282 do {
283 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
284 if (sense > 0)
285 swap (f1, f1 + size);
286 } while ((f1 += size2) < f2);
287 } else { /* Natural merge */
288 l2 = f2;
289 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
290 if ((cmp(f2-size, f2) > 0) != sense) {
291 p2 = *EVAL(p2) = f2 - list1 + list2;
292 if (sense > 0)
293 reverse(f1, f2-size);
294 f1 = f2;
295 }
296 }
297 if (sense > 0)
298 reverse (f1, f2-size);
299 f1 = f2;
300 if (f2 < last || cmp(f2 - size, f2) > 0)
301 p2 = *EVAL(p2) = f2 - list1 + list2;
302 else
303 p2 = *EVAL(p2) = list2 + n*size;
304 }
305 }
306#else /* pairwise merge only. */
307 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
308 p2 = *EVAL(p2) = p2 + size2;
309 if (cmp (f1, f1 + size) > 0)
310 swap(f1, f1 + size);
311 }
312#endif /* NATURAL */
313}
314
315/*
316 * This is to avoid out-of-bounds addresses in sorting the
317 * last 4 elements.
318 */
319static void
320insertionsort(u_char *a, size_t n, size_t size,
321 int (*cmp)(const void *, const void *))
322{
323 u_char *ai, *s, *t, *u, tmp;
324 int i;
325
326 for (ai = a+size; --n >= 1; ai += size)
327 for (t = ai; t > a; t -= size) {
328 u = t - size;
329 if (cmp(u, t) <= 0)
330 break;
331 swap(u, t);
332 }
333}
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
new file mode 100644
index 0000000000..977264aba5
--- /dev/null
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: mrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19long
20mrand48(void)
21{
22 __dorand48(__rand48_seed);
23 return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1];
24}
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
new file mode 100644
index 0000000000..f1f548c3af
--- /dev/null
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: nrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17long
18nrand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
22}
diff --git a/src/lib/libc/stdlib/posix_memalign.3 b/src/lib/libc/stdlib/posix_memalign.3
new file mode 100644
index 0000000000..05ec1b9d14
--- /dev/null
+++ b/src/lib/libc/stdlib/posix_memalign.3
@@ -0,0 +1,92 @@
1.\" $OpenBSD: posix_memalign.3,v 1.3 2012/06/18 17:03:52 matthew Exp $
2.\" Copyright (C) 2006 Jason Evans <jasone@FreeBSD.org>.
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice(s), this list of conditions and the following disclaimer as
10.\" the first lines of this file unmodified other than the possible
11.\" addition of one or more copyright notices.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice(s), this list of conditions and the following disclaimer in
14.\" the documentation and/or other materials provided with the
15.\" distribution.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
21.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28.\"
29.\" $FreeBSD: src/lib/libc/stdlib/posix_memalign.3,v 1.3 2007/03/28 04:32:51 jasone Exp $
30.\"
31.Dd $Mdocdate: June 18 2012 $
32.Dt POSIX_MEMALIGN 3
33.Os
34.Sh NAME
35.Nm posix_memalign
36.Nd aligned memory allocation
37.Sh SYNOPSIS
38.In stdlib.h
39.Ft int
40.Fn posix_memalign "void **ptr" "size_t alignment" "size_t size"
41.Sh DESCRIPTION
42The
43.Fn posix_memalign
44function allocates
45.Fa size
46bytes of memory such that the allocation's base address is a multiple of
47.Fa alignment ,
48and returns the allocation in the value pointed to by
49.Fa ptr .
50.Pp
51The requested
52.Fa alignment
53must be a power of 2 at least as large as
54.Fn sizeof "void *" .
55.Pp
56Memory that is allocated via
57.Fn posix_memalign
58can be used as an argument in subsequent calls to
59.Xr realloc 3
60and
61.Xr free 3 .
62.Sh RETURN VALUES
63The
64.Fn posix_memalign
65function returns the value 0 if successful; otherwise it returns an error value.
66.Sh ERRORS
67The
68.Fn posix_memalign
69function will fail if:
70.Bl -tag -width Er
71.It Bq Er EINVAL
72The
73.Fa alignment
74parameter is not a power of 2 at least as large as
75.Fn sizeof "void *" .
76.It Bq Er ENOMEM
77Memory allocation error.
78.El
79.Sh SEE ALSO
80.Xr free 3 ,
81.Xr malloc 3 ,
82.Xr realloc 3
83.Sh STANDARDS
84The
85.Fn posix_memalign
86function conforms to
87.St -p1003.1-2001 .
88.Sh HISTORY
89The
90.Fn posix_memalign
91function first appeared in
92.Ox 4.8 .
diff --git a/src/lib/libc/stdlib/posix_openpt.3 b/src/lib/libc/stdlib/posix_openpt.3
new file mode 100644
index 0000000000..376772bb07
--- /dev/null
+++ b/src/lib/libc/stdlib/posix_openpt.3
@@ -0,0 +1,102 @@
1.\" $OpenBSD: posix_openpt.3,v 1.3 2012/12/05 06:40:59 jmc Exp $
2.\"
3.\" Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: December 5 2012 $
18.Dt POSIX_OPENPT 3
19.Os
20.Sh NAME
21.Nm posix_openpt
22.Nd open a pseudo-terminal device
23.Sh SYNOPSIS
24.In stdlib.h
25.In fcntl.h
26.Ft int
27.Fn posix_openpt "int oflag"
28.Sh DESCRIPTION
29The
30.Fn posix_openpt
31function finds the next available pseudo-terminal and returns an open
32file descriptor for its master device.
33The path name of the slave device may be determined via the
34.Fn ptsname
35function.
36Note that the
37.Fn unlockpt
38and
39.Fn grantpt
40functions should be called before opening the slave device.
41.Pp
42The
43.Ar oflag
44argument is formed by bitwise-inclusive
45.Tn OR Ns 'ing
46the following values defined in
47.In fcntl.h :
48.Bl -tag -width O_NOCTTY -offset indent
49.It Dv O_RDWR
50Open for reading and writing.
51.It Dv O_NOCTTY
52Prevent the device from being made the controlling terminal for the session.
53This flag has no effect on
54.Ox
55and is included for compatibility with other systems.
56.El
57.Pp
58The
59.Dv O_RDWR
60flag must be specified in
61.Fa oflag .
62If
63.Fa oflag
64contains values other than those listed above,
65.Fn posix_openpt
66will return an error.
67.Sh RETURN VALUES
68If successful,
69.Fn posix_openpt
70returns a non-negative integer, the file descriptor for the
71pseudo-terminal master device.
72Otherwise, a value of \-1 is returned and
73.Va errno
74is set to indicate the error.
75.Sh ERRORS
76The
77.Fn posix_openpt
78function will fail if:
79.Bl -tag -width Er
80.It Bq Er EMFILE
81The per-process descriptor table is full.
82.It Bq Er ENFILE
83The system file table is full.
84.It Bq Er EINVAL
85The value of
86.Fa oflag
87is not valid.
88.El
89.Sh SEE ALSO
90.Xr ptsname 3 ,
91.Xr pty 4 ,
92.Xr tty 4
93.Sh STANDARDS
94The
95.Fn posix_openpt
96function conforms to
97.St -p1003.1-2001 .
98.Sh HISTORY
99The
100.Fn posix_openpt
101function appeared in
102.Ox 5.3 .
diff --git a/src/lib/libc/stdlib/posix_pty.c b/src/lib/libc/stdlib/posix_pty.c
new file mode 100644
index 0000000000..a2025ddbb6
--- /dev/null
+++ b/src/lib/libc/stdlib/posix_pty.c
@@ -0,0 +1,119 @@
1/* $OpenBSD: posix_pty.c,v 1.1 2012/12/03 20:08:33 millert Exp $ */
2
3/*
4 * Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/ioctl.h>
21#include <sys/stat.h>
22#include <sys/tty.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <paths.h>
26#include <stddef.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31int
32posix_openpt(int oflag)
33{
34 struct ptmget ptm;
35 int fd, mfd = -1;
36
37 /* User must specify O_RDWR in oflag. */
38 if (!(oflag & O_RDWR)) {
39 errno = EINVAL;
40 return -1;
41 }
42
43 /* Get pty master and slave (this API only uses the master). */
44 fd = open(PATH_PTMDEV, O_RDWR);
45 if (fd != -1) {
46 if (ioctl(fd, PTMGET, &ptm) != -1) {
47 close(ptm.sfd);
48 mfd = ptm.cfd;
49 }
50 close(fd);
51 }
52
53 return mfd;
54}
55
56/*
57 * Look up the name of the specified pty master fd.
58 * Note that the name returned does *not* include the /dev/ prefix.
59 * Returns the name on success and NULL on error, setting errno.
60 */
61static const char *
62ptmname(int mfd)
63{
64 struct stat sb;
65 const char *name;
66
67 /* Make sure it is a pty master. */
68 if (fstat(mfd, &sb) != 0)
69 return NULL;
70 if (!S_ISCHR(sb.st_mode)) {
71 errno = EINVAL;
72 return NULL;
73 }
74 name = devname(sb.st_rdev, S_IFCHR);
75 if (strncmp(name, "pty", 3) != 0) {
76 errno = EINVAL;
77 return NULL;
78 }
79 return name;
80}
81
82/*
83 * The PTMGET ioctl handles the mode and owner for us.
84 */
85int
86grantpt(int mfd)
87{
88 return ptmname(mfd) ? 0 : -1;
89}
90
91/*
92 * The PTMGET ioctl unlocks the pty master and slave for us.
93 */
94int
95unlockpt(int mfd)
96{
97 return ptmname(mfd) ? 0 : -1;
98}
99
100/*
101 * Look up the path of the slave pty that corresponds to the master fd.
102 * Returns the path if successful or NULL on error.
103 */
104char *
105ptsname(int mfd)
106{
107 const char *master;
108 static char slave[sizeof(((struct ptmget *)NULL)->sn)];
109
110 if ((master = ptmname(mfd)) == NULL)
111 return NULL;
112
113 /* Add /dev/ prefix and convert "pty" to "tty". */
114 strlcpy(slave, _PATH_DEV, sizeof(slave));
115 strlcat(slave, master, sizeof(slave));
116 slave[sizeof(_PATH_DEV) - 1] = 't';
117
118 return slave;
119}
diff --git a/src/lib/libc/stdlib/ptsname.3 b/src/lib/libc/stdlib/ptsname.3
new file mode 100644
index 0000000000..98705528f5
--- /dev/null
+++ b/src/lib/libc/stdlib/ptsname.3
@@ -0,0 +1,160 @@
1.\" $OpenBSD: ptsname.3,v 1.2 2012/12/04 18:42:16 millert Exp $
2.\"
3.\" Copyright (c) 2002 The FreeBSD Project, Inc.
4.\" All rights reserved.
5.\"
6.\" This software includes code contributed to the FreeBSD Project
7.\" by Ryan Younce of North Carolina State University.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution.
17.\" 3. Neither the name of the FreeBSD Project nor the names of its
18.\" contributors may be used to endorse or promote products derived from
19.\" this software without specific prior written permission.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT AND CONTRIBUTORS
22.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT
25.\" OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27.\" TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32.\"
33.\" $FreeBSD: head/lib/libc/stdlib/ptsname.3 240412 2012-09-12 17:54:09Z emaste $
34.\"
35.Dd $Mdocdate: December 4 2012 $
36.Dt PTSNAME 3
37.Os
38.Sh NAME
39.Nm grantpt ,
40.Nm ptsname ,
41.Nm unlockpt
42.Nd pseudo-terminal access functions
43.Sh SYNOPSIS
44.In stdlib.h
45.Ft int
46.Fn grantpt "int fildes"
47.Ft "char *"
48.Fn ptsname "int fildes"
49.Ft int
50.Fn unlockpt "int fildes"
51.Sh DESCRIPTION
52The
53.Fn grantpt ,
54.Fn ptsname ,
55and
56.Fn unlockpt
57functions allow access to pseudo-terminal devices.
58These three functions accept a file descriptor that references the
59master half of a pseudo-terminal pair.
60This file descriptor is created with
61.Xr posix_openpt 3 .
62.Pp
63The
64.Fn grantpt
65function is used to establish ownership and permissions
66of the slave device counterpart to the master device
67specified with
68.Fa fildes .
69The slave device's ownership is set to the real user ID
70of the calling process, and the permissions are set to
71user readable-writable and group writable.
72The group owner of the slave device is also set to the
73group
74.Dq Li tty .
75.Pp
76The
77.Fn ptsname
78function returns the full path name of the slave device
79counterpart to the master device specified with
80.Fa fildes .
81This value can be used
82to subsequently open the appropriate slave after
83.Xr posix_openpt 3
84and
85.Fn grantpt
86have been called.
87.Pp
88The
89.Fn unlockpt
90function clears the lock held on the pseudo-terminal pair
91for the master device specified with
92.Fa fildes .
93.Sh RETURN VALUES
94.Rv -std grantpt unlockpt
95.Pp
96The
97.Fn ptsname
98function returns a pointer to the name
99of the slave device on success; otherwise a
100.Dv NULL
101pointer is returned.
102.Sh ERRORS
103The
104.Fn grantpt ,
105.Fn ptsname
106and
107.Fn unlockpt
108functions may fail and set
109.Va errno
110to:
111.Bl -tag -width Er
112.It Bq Er EBADF
113.Fa fildes
114is not a valid open file descriptor.
115.It Bq Er EINVAL
116.Fa fildes
117is not a master pseudo-terminal device.
118.El
119.Pp
120In addition, the
121.Fn grantpt
122function may set
123.Va errno
124to:
125.Bl -tag -width Er
126.It Bq Er EACCES
127The slave pseudo-terminal device could not be accessed.
128.El
129.Sh SEE ALSO
130.Xr posix_openpt 3 ,
131.Xr pty 4 ,
132.Xr tty 4
133.Sh STANDARDS
134The
135.Fn ptsname
136function conforms to
137.St -p1003.1-2008 .
138.Pp
139This implementation of
140.Fn grantpt
141and
142.Fn unlockpt
143does not conform to
144.St -p1003.1-2008 ,
145because it depends on
146.Xr posix_openpt 3
147to create the pseudo-terminal device with proper permissions in place.
148It only validates whether
149.Fa fildes
150is a valid pseudo-terminal master device.
151Future revisions of the specification will likely allow this behaviour,
152as stated by the Austin Group.
153.Sh HISTORY
154The
155.Fn grantpt ,
156.Fn ptsname
157and
158.Fn unlockpt
159functions appeared in
160.Ox 5.3 .
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
new file mode 100644
index 0000000000..6703072e72
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.3
@@ -0,0 +1,56 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: qabs.3,v 1.13 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt QABS 3
36.Os
37.Sh NAME
38.Nm qabs
39.Nd return the absolute value of a quad integer
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft quad_t
43.Fn qabs "quad_t j"
44.Sh DESCRIPTION
45The
46.Fn qabs
47function returns the absolute value of the quad integer
48.Fa j .
49.Sh SEE ALSO
50.Xr abs 3 ,
51.Xr cabs 3 ,
52.Xr floor 3 ,
53.Xr imaxabs 3 ,
54.Xr labs 3
55.Sh BUGS
56The 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
new file mode 100644
index 0000000000..656b93c822
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: qabs.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdlib.h>
32
33quad_t
34qabs(quad_t j)
35{
36 return(j < 0 ? -j : j);
37}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
new file mode 100644
index 0000000000..5f5275493e
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -0,0 +1,61 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: qdiv.3,v 1.10 2013/06/05 03:39:23 tedu Exp $
33.\"
34.Dd $Mdocdate: June 5 2013 $
35.Dt QDIV 3
36.Os
37.Sh NAME
38.Nm qdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft qdiv_t
43.Fn qdiv "quad_t num" "quad_t denom"
44.Sh DESCRIPTION
45The
46.Fn qdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li qdiv_t
51that contains two
52.Li quad integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr imaxdiv 3 ,
60.Xr ldiv 3 ,
61.Xr lldiv 3
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
new file mode 100644
index 0000000000..f3db0915ed
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: qdiv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <stdlib.h> /* qdiv_t */
35
36qdiv_t
37qdiv(quad_t num, quad_t denom)
38{
39 qdiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
new file mode 100644
index 0000000000..4481a96ee4
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.3
@@ -0,0 +1,238 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. 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. 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.\" $OpenBSD: qsort.3,v 1.17 2013/07/17 05:42:11 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 17 2013 $
35.Dt QSORT 3
36.Os
37.Sh NAME
38.Nm qsort ,
39.Nm heapsort ,
40.Nm mergesort
41.Nd sort functions
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft void
45.Fn qsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
46.Ft int
47.Fn heapsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
48.Ft int
49.Fn mergesort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
50.Sh DESCRIPTION
51The
52.Fn qsort
53function is a modified partition-exchange sort, or quicksort.
54The
55.Fn heapsort
56function is a modified selection sort.
57The
58.Fn mergesort
59function is a modified merge sort with exponential search
60intended for sorting data with pre-existing order.
61.Pp
62The
63.Fn qsort
64and
65.Fn heapsort
66functions sort an array of
67.Fa nmemb
68objects, the initial member of which is pointed to by
69.Fa base .
70The size of each object is specified by
71.Fa size .
72.Fn mergesort
73behaves similarly, but
74.Em requires
75that
76.Fa size
77be greater than
78.Dq "sizeof(void *) / 2" .
79.Pp
80The contents of the array
81.Fa base
82are sorted in ascending order according to
83a comparison function pointed to by
84.Fa compar ,
85which requires two arguments pointing to the objects being
86compared.
87.Pp
88The comparison function must return an integer less than, equal to, or
89greater than zero if the first argument is considered to be respectively
90less than, equal to, or greater than the second.
91.Pp
92The functions
93.Fn qsort
94and
95.Fn heapsort
96are
97.Em not
98stable, that is, if two members compare as equal, their order in
99the sorted array is undefined.
100The function
101.Fn mergesort
102is stable.
103.Pp
104The
105.Fn qsort
106function is an implementation of C.A.R. Hoare's
107.Dq quicksort
108algorithm,
109a variant of partition-exchange sorting; in particular, see D.E. Knuth's
110Algorithm Q.
111.Fn qsort
112takes O N lg N average time.
113This implementation uses median selection to avoid its
114O N**2 worst-case behavior.
115.Pp
116The
117.Fn heapsort
118function is an implementation of J.W.J. William's
119.Dq heapsort
120algorithm,
121a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
122.Fn heapsort
123takes O N lg N worst-case time.
124This implementation of
125.Fn heapsort
126is implemented without recursive function calls.
127.Pp
128The function
129.Fn mergesort
130requires additional memory of size
131.Fa nmemb *
132.Fa size
133bytes; it should be used only when space is not at a premium.
134.Fn mergesort
135is optimized for data with pre-existing order; its worst case
136time is O N lg N; its best case is O N.
137.Pp
138Normally,
139.Fn qsort
140is faster than
141.Fn mergesort ,
142which is faster than
143.Fn heapsort .
144Memory availability and pre-existing order in the data can make this untrue.
145.Sh RETURN VALUES
146The
147.Fn qsort
148function returns no value.
149.Pp
150Upon successful completion,
151.Fn heapsort
152and
153.Fn mergesort
154return 0.
155Otherwise, they return \-1 and the global variable
156.Va errno
157is set to indicate the error.
158.Sh ERRORS
159The
160.Fn heapsort
161and
162.Fn mergesort
163functions succeed unless:
164.Bl -tag -width Er
165.It Bq Er EINVAL
166The
167.Fa size
168argument is zero, or the
169.Fa size
170argument to
171.Fn mergesort
172is less than
173.Dq "sizeof(void *) / 2" .
174.It Bq Er ENOMEM
175.Fn heapsort
176or
177.Fn mergesort
178were unable to allocate memory.
179.El
180.Sh SEE ALSO
181.Xr sort 1 ,
182.Xr radixsort 3
183.Rs
184.%A Hoare, C.A.R.
185.%D 1962
186.%T "Quicksort"
187.%J "The Computer Journal"
188.%V 5:1
189.%P pp. 10-15
190.Re
191.Rs
192.%A Williams, J.W.J
193.%D 1964
194.%T "Heapsort"
195.%J "Communications of the ACM"
196.%V 7:1
197.%P pp. 347\-348
198.Re
199.Rs
200.%A Knuth, D.E.
201.%D 1968
202.%B "The Art of Computer Programming"
203.%V Vol. 3
204.%T "Sorting and Searching"
205.%P pp. 114\-123, 145\-149
206.Re
207.Rs
208.%A McIlroy, P.M.
209.%T "Optimistic Sorting and Information Theoretic Complexity"
210.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
211.%P pp. 467\-464
212.%D January 1993
213.Re
214.Rs
215.%A Bentley, J.L.
216.%A McIlroy, M.D.
217.%T "Engineering a Sort Function"
218.%J "Software \- Practice and Experience"
219.%V Vol. 23(11)
220.%P pp. 1249\-1265
221.%D November 1993
222.Re
223.Sh STANDARDS
224Previous versions of
225.Fn qsort
226did not permit the comparison routine itself to call
227.Fn qsort .
228This is no longer true.
229.Pp
230The
231.Fn qsort
232function conforms to
233.St -ansiC .
234.Sh HISTORY
235A
236.Fn qsort
237function first appeared in
238.At v3 .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
new file mode 100644
index 0000000000..f28449fb5b
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.c
@@ -0,0 +1,162 @@
1/* $OpenBSD: qsort.c,v 1.11 2010/02/08 11:04:07 otto Exp $ */
2/*-
3 * Copyright (c) 1992, 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. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <stdlib.h>
33
34static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
35static __inline void swapfunc(char *, char *, size_t, int);
36
37#define min(a, b) (a) < (b) ? a : b
38
39/*
40 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
41 */
42#define swapcode(TYPE, parmi, parmj, n) { \
43 size_t i = (n) / sizeof (TYPE); \
44 TYPE *pi = (TYPE *) (parmi); \
45 TYPE *pj = (TYPE *) (parmj); \
46 do { \
47 TYPE t = *pi; \
48 *pi++ = *pj; \
49 *pj++ = t; \
50 } while (--i > 0); \
51}
52
53#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
54 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
55
56static __inline void
57swapfunc(char *a, char *b, size_t n, int swaptype)
58{
59 if (swaptype <= 1)
60 swapcode(long, a, b, n)
61 else
62 swapcode(char, a, b, n)
63}
64
65#define swap(a, b) \
66 if (swaptype == 0) { \
67 long t = *(long *)(a); \
68 *(long *)(a) = *(long *)(b); \
69 *(long *)(b) = t; \
70 } else \
71 swapfunc(a, b, es, swaptype)
72
73#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
74
75static __inline char *
76med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
77{
78 return cmp(a, b) < 0 ?
79 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
80 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
81}
82
83void
84qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
85{
86 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
87 int cmp_result, swaptype, swap_cnt;
88 size_t d, r;
89 char *a = aa;
90
91loop: SWAPINIT(a, es);
92 swap_cnt = 0;
93 if (n < 7) {
94 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
95 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
96 pl -= es)
97 swap(pl, pl - es);
98 return;
99 }
100 pm = (char *)a + (n / 2) * es;
101 if (n > 7) {
102 pl = (char *)a;
103 pn = (char *)a + (n - 1) * es;
104 if (n > 40) {
105 d = (n / 8) * es;
106 pl = med3(pl, pl + d, pl + 2 * d, cmp);
107 pm = med3(pm - d, pm, pm + d, cmp);
108 pn = med3(pn - 2 * d, pn - d, pn, cmp);
109 }
110 pm = med3(pl, pm, pn, cmp);
111 }
112 swap(a, pm);
113 pa = pb = (char *)a + es;
114
115 pc = pd = (char *)a + (n - 1) * es;
116 for (;;) {
117 while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
118 if (cmp_result == 0) {
119 swap_cnt = 1;
120 swap(pa, pb);
121 pa += es;
122 }
123 pb += es;
124 }
125 while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
126 if (cmp_result == 0) {
127 swap_cnt = 1;
128 swap(pc, pd);
129 pd -= es;
130 }
131 pc -= es;
132 }
133 if (pb > pc)
134 break;
135 swap(pb, pc);
136 swap_cnt = 1;
137 pb += es;
138 pc -= es;
139 }
140 if (swap_cnt == 0) { /* Switch to insertion sort */
141 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
142 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
143 pl -= es)
144 swap(pl, pl - es);
145 return;
146 }
147
148 pn = (char *)a + n * es;
149 r = min(pa - (char *)a, pb - pa);
150 vecswap(a, pb - r, r);
151 r = min(pd - pc, pn - pd - es);
152 vecswap(pb, pn - r, r);
153 if ((r = pb - pa) > es)
154 qsort(a, r / es, es, cmp);
155 if ((r = pd - pc) > es) {
156 /* Iterate rather than recurse to save stack space */
157 a = pn - r;
158 n = r / es;
159 goto loop;
160 }
161/* qsort(pn - r, r / es, es, cmp);*/
162}
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
new file mode 100644
index 0000000000..e62f760270
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -0,0 +1,155 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: radixsort.3,v 1.12 2013/06/05 03:39:23 tedu Exp $
29.\"
30.Dd $Mdocdate: June 5 2013 $
31.Dt RADIXSORT 3
32.Os
33.Sh NAME
34.Nm radixsort ,
35.Nm sradixsort
36.Nd radix sort
37.Sh SYNOPSIS
38.In limits.h
39.In stdlib.h
40.Ft int
41.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
42.Ft int
43.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
44.Sh DESCRIPTION
45The
46.Fn radixsort
47and
48.Fn sradixsort
49functions are implementations of radix sort.
50.Pp
51These functions sort an array of
52.Fa nmemb
53pointers to byte strings.
54The initial member is referenced by
55.Fa base .
56The byte strings may contain any values; the end of each string
57is denoted by the user-specified value
58.Fa endbyte .
59.Pp
60Applications may specify a sort order by providing the
61.Fa table
62argument.
63If non-null,
64.Fa table
65must reference an array of
66.Dv UCHAR_MAX
67+ 1 bytes which contains the sort weight of each possible byte value.
68The end-of-string byte must have a sort weight of 0 or 255
69(for sorting in reverse order).
70More than one byte may have the same sort weight.
71The
72.Fa table
73argument is useful for applications which wish to sort different characters
74equally; for example, providing a table with the same weights
75for A\-Z as for a\-z will result in a case-insensitive sort.
76If
77.Fa table
78is
79.Dv NULL ,
80the contents of the array are sorted in ascending order according to the
81.Tn ASCII
82order of the byte strings they reference and
83.Fa endbyte
84has a sorting weight of 0.
85.Pp
86The
87.Fn sradixsort
88function is stable; that is, if two elements compare as equal, their
89order in the sorted array is unchanged.
90The
91.Fn sradixsort
92function uses additional memory sufficient to hold
93.Fa nmemb
94pointers.
95.Pp
96The
97.Fn radixsort
98function is not stable, but uses no additional memory.
99.Pp
100These functions are variants of most-significant-byte radix sorting; in
101particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
102They take linear time relative to the number of bytes in the strings.
103.Sh RETURN VALUES
104Upon successful completion 0 is returned.
105Otherwise, \-1 is returned and the global variable
106.Va errno
107is set to indicate the error.
108.Sh ERRORS
109.Bl -tag -width Er
110.It Bq Er EINVAL
111The value of the
112.Fa endbyte
113element of
114.Fa table
115is not 0 or 255.
116.El
117.Pp
118Additionally, the
119.Fn sradixsort
120function may fail and set
121.Va errno
122for any of the errors specified for the library routine
123.Xr malloc 3 .
124.Sh SEE ALSO
125.Xr sort 1 ,
126.Xr qsort 3
127.Rs
128.%A Knuth, D.E.
129.%D 1968
130.%B "The Art of Computer Programming"
131.%T "Sorting and Searching"
132.%V Vol. 3
133.%P pp. 170-178
134.Re
135.Rs
136.%A Paige, R.
137.%D 1987
138.%T "Three Partition Refinement Algorithms"
139.%J "SIAM J. Comput."
140.%V Vol. 16
141.%N No. 6
142.Re
143.Rs
144.%A McIlroy, P.
145.%D 1993
146.%B "Engineering Radix Sort"
147.%T "Computing Systems"
148.%V Vol. 6:1
149.%P pp. 5-27
150.Re
151.Sh HISTORY
152The
153.Fn radixsort
154function first appeared in
155.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
new file mode 100644
index 0000000000..49d03b52d5
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,294 @@
1/* $OpenBSD: radixsort.c,v 1.9 2007/09/02 15:19:17 deraadt Exp $ */
2/*-
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Peter McIlroy and by Dan Bernstein at New York University,
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * Radixsort routines.
36 *
37 * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
38 * Use radixsort(a, n, trace, endchar) for this case.
39 *
40 * For stable sorting (using N extra pointers) use sradixsort(), which calls
41 * r_sort_b().
42 *
43 * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
44 * "Engineering Radix Sort".
45 */
46
47#include <sys/types.h>
48#include <stdlib.h>
49#include <errno.h>
50
51typedef struct {
52 const u_char **sa;
53 int sn, si;
54} stack;
55
56static __inline void simplesort
57(const u_char **, int, int, const u_char *, u_int);
58static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
59static void r_sort_b(const u_char **,
60 const u_char **, int, int, const u_char *, u_int);
61
62#define THRESHOLD 20 /* Divert to simplesort(). */
63#define SIZE 512 /* Default stack size. */
64
65#define SETUP { \
66 if (tab == NULL) { \
67 tr = tr0; \
68 for (c = 0; c < endch; c++) \
69 tr0[c] = c + 1; \
70 tr0[c] = 0; \
71 for (c++; c < 256; c++) \
72 tr0[c] = c; \
73 endch = 0; \
74 } else { \
75 endch = tab[endch]; \
76 tr = tab; \
77 if (endch != 0 && endch != 255) { \
78 errno = EINVAL; \
79 return (-1); \
80 } \
81 } \
82}
83
84int
85radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
86{
87 const u_char *tr;
88 int c;
89 u_char tr0[256];
90
91 SETUP;
92 r_sort_a(a, n, 0, tr, endch);
93 return (0);
94}
95
96int
97sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
98{
99 const u_char *tr, **ta;
100 int c;
101 u_char tr0[256];
102
103 SETUP;
104 if (n < THRESHOLD)
105 simplesort(a, n, 0, tr, endch);
106 else {
107 if ((ta = calloc(n, sizeof(a))) == NULL)
108 return (-1);
109 r_sort_b(a, ta, n, 0, tr, endch);
110 free(ta);
111 }
112 return (0);
113}
114
115#define empty(s) (s >= sp)
116#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
117#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
118#define swap(a, b, t) t = a, a = b, b = t
119
120/* Unstable, in-place sort. */
121void
122r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
123{
124 static int count[256], nc, bmin;
125 int c;
126 const u_char **ak, *r;
127 stack s[SIZE], *sp, *sp0, *sp1, temp;
128 int *cp, bigc;
129 const u_char **an, *t, **aj, **top[256];
130
131 /* Set up stack. */
132 sp = s;
133 push(a, n, i);
134 while (!empty(s)) {
135 pop(a, n, i);
136 if (n < THRESHOLD) {
137 simplesort(a, n, i, tr, endch);
138 continue;
139 }
140 an = a + n;
141
142 /* Make character histogram. */
143 if (nc == 0) {
144 bmin = 255; /* First occupied bin, excluding eos. */
145 for (ak = a; ak < an;) {
146 c = tr[(*ak++)[i]];
147 if (++count[c] == 1 && c != endch) {
148 if (c < bmin)
149 bmin = c;
150 nc++;
151 }
152 }
153 if (sp + nc > s + SIZE) { /* Get more stack. */
154 r_sort_a(a, n, i, tr, endch);
155 continue;
156 }
157 }
158
159 /*
160 * Set top[]; push incompletely sorted bins onto stack.
161 * top[] = pointers to last out-of-place element in bins.
162 * count[] = counts of elements in bins.
163 * Before permuting: top[c-1] + count[c] = top[c];
164 * during deal: top[c] counts down to top[c-1].
165 */
166 sp0 = sp1 = sp; /* Stack position of biggest bin. */
167 bigc = 2; /* Size of biggest bin. */
168 if (endch == 0) /* Special case: set top[eos]. */
169 top[0] = ak = a + count[0];
170 else {
171 ak = a;
172 top[255] = an;
173 }
174 for (cp = count + bmin; nc > 0; cp++) {
175 while (*cp == 0) /* Find next non-empty pile. */
176 cp++;
177 if (*cp > 1) {
178 if (*cp > bigc) {
179 bigc = *cp;
180 sp1 = sp;
181 }
182 push(ak, *cp, i+1);
183 }
184 top[cp-count] = ak += *cp;
185 nc--;
186 }
187 swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
188
189 /*
190 * Permute misplacements home. Already home: everything
191 * before aj, and in bin[c], items from top[c] on.
192 * Inner loop:
193 * r = next element to put in place;
194 * ak = top[r[i]] = location to put the next element.
195 * aj = bottom of 1st disordered bin.
196 * Outer loop:
197 * Once the 1st disordered bin is done, ie. aj >= ak,
198 * aj<-aj + count[c] connects the bins in a linked list;
199 * reset count[c].
200 */
201 for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
202 for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
203 swap(*ak, r, t);
204 }
205}
206
207/* Stable sort, requiring additional memory. */
208void
209r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
210 u_int endch)
211{
212 static int count[256], nc, bmin;
213 int c;
214 const u_char **ak, **ai;
215 stack s[512], *sp, *sp0, *sp1, temp;
216 const u_char **top[256];
217 int *cp, bigc;
218
219 sp = s;
220 push(a, n, i);
221 while (!empty(s)) {
222 pop(a, n, i);
223 if (n < THRESHOLD) {
224 simplesort(a, n, i, tr, endch);
225 continue;
226 }
227
228 if (nc == 0) {
229 bmin = 255;
230 for (ak = a + n; --ak >= a;) {
231 c = tr[(*ak)[i]];
232 if (++count[c] == 1 && c != endch) {
233 if (c < bmin)
234 bmin = c;
235 nc++;
236 }
237 }
238 if (sp + nc > s + SIZE) {
239 r_sort_b(a, ta, n, i, tr, endch);
240 continue;
241 }
242 }
243
244 sp0 = sp1 = sp;
245 bigc = 2;
246 if (endch == 0) {
247 top[0] = ak = a + count[0];
248 count[0] = 0;
249 } else {
250 ak = a;
251 top[255] = a + n;
252 count[255] = 0;
253 }
254 for (cp = count + bmin; nc > 0; cp++) {
255 while (*cp == 0)
256 cp++;
257 if ((c = *cp) > 1) {
258 if (c > bigc) {
259 bigc = c;
260 sp1 = sp;
261 }
262 push(ak, c, i+1);
263 }
264 top[cp-count] = ak += c;
265 *cp = 0; /* Reset count[]. */
266 nc--;
267 }
268 swap(*sp0, *sp1, temp);
269
270 for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
271 *--ak = *--ai;
272 for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
273 *--top[tr[(*ak)[i]]] = *ak;
274 }
275}
276
277static __inline void
278simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
279 /* insertion sort */
280{
281 u_char ch;
282 const u_char **ak, **ai, *s, *t;
283
284 for (ak = a+1; --n >= 1; ak++)
285 for (ai = ak; ai > a; ai--) {
286 for (s = ai[0] + b, t = ai[-1] + b;
287 (ch = tr[*s]) != endch; s++, t++)
288 if (ch != tr[*t])
289 break;
290 if (ch >= tr[*t])
291 break;
292 swap(ai[0], ai[-1], s);
293 }
294}
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
new file mode 100644
index 0000000000..75395976f8
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.3
@@ -0,0 +1,105 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: rand.3,v 1.15 2014/04/07 17:57:56 schwarze Exp $
33.\"
34.Dd $Mdocdate: April 7 2014 $
35.Dt RAND 3
36.Os
37.Sh NAME
38.Nm rand ,
39.Nm rand_r ,
40.Nm srand
41.Nd bad random number generator
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft void
45.Fn srand "unsigned int seed"
46.Ft int
47.Fn rand void
48.Ft int
49.Fn rand_r "unsigned int *seed"
50.Sh DESCRIPTION
51.Bf -symbolic
52These interfaces are obsoleted by
53.Xr random 3 .
54.Ef
55.Pp
56The
57.Fn rand
58function computes a sequence of pseudo-random integers in the range
59of 0 to
60.Dv RAND_MAX
61(as defined by the header file
62.In stdlib.h ) .
63.Pp
64The
65.Fn srand
66function sets its argument as the seed for a new sequence of
67pseudo-random numbers to be returned by
68.Fn rand .
69These sequences are repeatable by calling
70.Fn srand
71with the same seed value.
72.Pp
73If no seed value is provided, the functions are automatically
74seeded with a value of 1.
75.Pp
76The
77.Fn rand_r
78is a thread-safe version of
79.Fn rand .
80Storage for the seed must be provided through the
81.Fa seed
82argument, and needs to have been initialized by the caller.
83.Sh SEE ALSO
84.Xr arc4random 3 ,
85.Xr rand48 3 ,
86.Xr random 3
87.Sh STANDARDS
88The
89.Fn rand
90and
91.Fn srand
92functions conform to
93.St -ansiC .
94.Pp
95The
96.Fn rand_r
97function conforms to
98.St -p1003.1-2008 .
99.Sh HISTORY
100The functions
101.Fn rand
102and
103.Fn srand
104first appeared in
105.At v3 .
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
new file mode 100644
index 0000000000..6860dd4f71
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.c
@@ -0,0 +1,67 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/types.h>
31#include <stdlib.h>
32
33static u_int next = 1;
34
35int
36rand_r(u_int *seed)
37{
38 *seed = *seed * 1103515245 + 12345;
39 return (*seed % ((u_int)RAND_MAX + 1));
40}
41
42#if defined(APIWARN)
43__warn_references(rand_r,
44 "warning: rand_r() isn't random; consider using arc4random()");
45#endif
46
47int
48rand(void)
49{
50 return (rand_r(&next));
51}
52
53#if defined(APIWARN)
54__warn_references(rand,
55 "warning: rand() isn't random; consider using arc4random()");
56#endif
57
58void
59srand(u_int seed)
60{
61 next = seed;
62}
63
64#if defined(APIWARN)
65__warn_references(srand,
66 "warning: srand() seed choices are invariably poor");
67#endif
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
new file mode 100644
index 0000000000..8b7c572fb4
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.3
@@ -0,0 +1,179 @@
1.\" Copyright (c) 1993 Martin Birgmeier
2.\" All rights reserved.
3.\"
4.\" You may redistribute unmodified or modified versions of this source
5.\" code provided that the above copyright notice and this and the
6.\" following conditions are retained.
7.\"
8.\" This software is provided ``as is'', and comes with no warranties
9.\" of any kind. I shall in no event be liable for anything that happens
10.\" to anyone/anything when using this software.
11.\"
12.\" $OpenBSD: rand48.3,v 1.14 2014/01/21 23:25:03 deraadt Exp $
13.\"
14.Dd $Mdocdate: January 21 2014 $
15.Dt RAND48 3
16.Os
17.Sh NAME
18.Nm drand48 ,
19.Nm erand48 ,
20.Nm lrand48 ,
21.Nm nrand48 ,
22.Nm mrand48 ,
23.Nm jrand48 ,
24.Nm srand48 ,
25.Nm seed48 ,
26.Nm lcong48
27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS
29.In stdlib.h
30.Ft double
31.Fn drand48 void
32.Ft double
33.Fn erand48 "unsigned short xseed[3]"
34.Ft long
35.Fn lrand48 void
36.Ft long
37.Fn nrand48 "unsigned short xseed[3]"
38.Ft long
39.Fn mrand48 void
40.Ft long
41.Fn jrand48 "unsigned short xseed[3]"
42.Ft void
43.Fn srand48 "long seed"
44.Ft "unsigned short *"
45.Fn seed48 "unsigned short xseed[3]"
46.Ft void
47.Fn lcong48 "unsigned short p[7]"
48.Sh DESCRIPTION
49The
50.Fn rand48
51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size.
53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m
55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
59r(n) is called the seed of the random number generator.
60.Pp
61For all the six generator routines described next, the first
62computational step is to perform a single iteration of the algorithm.
63.Pp
64.Fn drand48
65and
66.Fn erand48
67return values of type double.
68The full 48 bits of r(n+1) are
69loaded into the mantissa of the returned value, with the exponent set
70such that the values produced lie in the interval [0.0, 1.0].
71.Pp
72.Fn lrand48
73and
74.Fn nrand48
75return values of type long in the range
76[0, 2**31-1].
77The high-order (31) bits of
78r(n+1) are loaded into the lower bits of the returned value, with
79the topmost (sign) bit set to zero.
80.Pp
81.Fn mrand48
82and
83.Fn jrand48
84return values of type long in the range
85[-2**31, 2**31-1].
86The high-order (32) bits of r(n+1) are loaded into the returned value.
87.Pp
88.Fn drand48 ,
89.Fn lrand48 ,
90and
91.Fn mrand48
92use an internal buffer to store r(n).
93For these functions
94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
95.Pp
96On the other hand,
97.Fn erand48 ,
98.Fn nrand48 ,
99and
100.Fn jrand48
101use a user-supplied buffer to store the seed r(n),
102which consists of an array of 3 shorts, where the zeroth member
103holds the least significant bits.
104.Pp
105All functions share the same multiplicand and addend.
106.Pp
107.Fn srand48
108is used to initialize the internal buffer r(n) of
109.Fn drand48 ,
110.Fn lrand48 ,
111and
112.Fn mrand48
113such that the 32 bits of the seed value are copied into the upper 32 bits
114of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
115Additionally, the constant multiplicand and addend of the algorithm are
116reset to the default values given above.
117.Pp
118.Fn seed48
119also initializes the internal buffer r(n) of
120.Fn drand48 ,
121.Fn lrand48 ,
122and
123.Fn mrand48 ,
124but here all 48 bits of the seed can be specified in an array of 3 shorts,
125where the zeroth member specifies the lowest bits.
126Again, the constant multiplicand and addend of the algorithm are
127reset to the default values given above.
128.Fn seed48
129returns a pointer to an array of 3 shorts which contains the old seed.
130This array is statically allocated, so its contents are lost after
131each new call to
132.Fn seed48 .
133.Pp
134Finally,
135.Fn lcong48
136allows full control over the multiplicand and addend used in
137.Fn drand48 ,
138.Fn erand48 ,
139.Fn lrand48 ,
140.Fn nrand48 ,
141.Fn mrand48 ,
142and
143.Fn jrand48 ,
144and the seed used in
145.Fn drand48 ,
146.Fn lrand48 ,
147and
148.Fn mrand48 .
149An array of 7 shorts is passed as parameter; the first three shorts are
150used to initialize the seed; the second three are used to initialize the
151multiplicand; and the last short is used to initialize the addend.
152It is thus not possible to use values greater than 0xffff as the addend.
153.Pp
154Note that all three methods of seeding the random number generator
155always also set the multiplicand and addend for any of the six
156generator calls.
157.Pp
158For a more powerful random number generator, see
159.Xr arc4random 3 .
160.Sh SEE ALSO
161.Xr arc4random 3 ,
162.Xr rand 3 ,
163.Xr random 3
164.Sh STANDARDS
165The
166.Fn drand48 ,
167.Fn erand48 ,
168.Fn jrand48 ,
169.Fn lcong48 ,
170.Fn lrand48 ,
171.Fn mrand48 ,
172.Fn nrand48 ,
173.Fn seed48 ,
174and
175.Fn srand48
176functions conform to
177.St -p1003.1-2008 .
178.Sh AUTHORS
179Martin Birgmeier
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
new file mode 100644
index 0000000000..afa49f65f3
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
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
11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
14 */
15
16#ifndef _RAND48_H_
17#define _RAND48_H_
18
19#include <math.h>
20#include <stdlib.h>
21
22void __dorand48(unsigned short[3]);
23
24#define RAND48_SEED_0 (0x330e)
25#define RAND48_SEED_1 (0xabcd)
26#define RAND48_SEED_2 (0x1234)
27#define RAND48_MULT_0 (0xe66d)
28#define RAND48_MULT_1 (0xdeec)
29#define RAND48_MULT_2 (0x0005)
30#define RAND48_ADD (0x000b)
31
32#endif /* _RAND48_H_ */
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
new file mode 100644
index 0000000000..fdb78848d8
--- /dev/null
+++ b/src/lib/libc/stdlib/random.3
@@ -0,0 +1,185 @@
1.\" Copyright (c) 1983, 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. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: random.3,v 1.21 2013/06/05 03:39:23 tedu Exp $
29.\"
30.Dd $Mdocdate: June 5 2013 $
31.Dt RANDOM 3
32.Os
33.Sh NAME
34.Nm random ,
35.Nm srandom ,
36.Nm srandomdev ,
37.Nm initstate ,
38.Nm setstate
39.Nd better random number generator; routines for changing generators
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft long
43.Fn random void
44.Ft void
45.Fn srandom "unsigned int seed"
46.Ft void
47.Fn srandomdev void
48.Ft char *
49.Fn initstate "unsigned int seed" "char *state" "size_t n"
50.Ft char *
51.Fn setstate "char *state"
52.Sh DESCRIPTION
53The
54.Fn random
55function uses a non-linear additive feedback random number generator employing
56a default table of size 31 long integers to return successive pseudo-random
57numbers in the range from 0 to (2**31)\-1.
58The period of this random number generator is very large, approximately
5916*((2**31)\-1).
60.Pp
61The
62.Fn random
63and
64.Fn srandom
65functions have (almost) the same calling sequence and initialization
66properties as
67.Xr rand 3 Ns / Ns Xr srand 3 .
68The difference is that
69.Xr rand
70produces a much less random sequence \(em in fact, the low dozen bits
71generated by rand go through a cyclic pattern.
72All the bits generated by
73.Fn random
74are usable.
75For example,
76.Sq Li random()&01
77will produce a random binary
78value.
79.Pp
80Like
81.Xr rand 3 ,
82.Fn random
83will by default produce a sequence of numbers that can be duplicated
84by calling
85.Fn srandom
86with
87.Ql 1
88as the seed.
89.Pp
90The
91.Fn srandomdev
92routine initializes a state array using
93random numbers obtained from the kernel,
94suitable for cryptographic use.
95Note that this particular seeding procedure can generate
96states which are impossible to reproduce by calling
97.Fn srandom
98with any value, since the succeeding terms in the
99state buffer are no longer derived from the LC algorithm applied to
100a fixed seed.
101.Pp
102The
103.Fn initstate
104routine allows a state array, passed in as an argument, to be initialized
105for future use.
106The size of the state array (in bytes) is used by
107.Fn initstate
108to decide how sophisticated a random number generator it should use \(em the
109more state, the better the random numbers will be.
110(Current "optimal" values for the amount of state information are
1118, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
112the nearest known amount.
113Using less than 8 bytes will cause an error.)
114The seed for the initialization (which specifies a starting point for
115the random number sequence, and provides for restarting at the same
116point) is also an argument.
117The
118.Fn initstate
119function returns a pointer to the previous state information array.
120.Pp
121Once a state has been initialized, the
122.Fn setstate
123routine provides for rapid switching between states.
124The
125.Fn setstate
126function returns a pointer to the previous state array; its
127argument state array is used for further random number generation
128until the next call to
129.Fn initstate
130or
131.Fn setstate .
132.Pp
133Once a state array has been initialized, it may be restarted at a
134different point either by calling
135.Fn initstate
136(with the desired seed, the state array, and its size) or by calling
137both
138.Fn setstate
139(with the state array) and
140.Fn srandom
141(with the desired seed).
142The advantage of calling both
143.Fn setstate
144and
145.Fn srandom
146is that the size of the state array does not have to be remembered after
147it is initialized.
148.Pp
149With 256 bytes of state information, the period of the random number
150generator is greater than 2**69
151which should be sufficient for most purposes.
152.Sh DIAGNOSTICS
153If
154.Fn initstate
155is called with less than 8 bytes of state information, or if
156.Fn setstate
157detects that the state information has been garbled, error
158messages are printed on the standard error output.
159.Sh SEE ALSO
160.Xr arc4random 3 ,
161.Xr drand48 3 ,
162.Xr rand 3 ,
163.Xr random 4
164.Sh STANDARDS
165The
166.Fn random ,
167.Fn srandom ,
168.Fn initstate ,
169and
170.Fn setstate
171functions conform to
172.St -xpg4.2 .
173.Pp
174The
175.Fn srandomdev
176function is an extension.
177.Sh HISTORY
178These
179functions appeared in
180.Bx 4.2 .
181.Sh AUTHORS
182.An Earl T. Cohen
183.Sh BUGS
184About 2/3 the speed of
185.Xr rand 3 .
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
new file mode 100644
index 0000000000..00edf2dca1
--- /dev/null
+++ b/src/lib/libc/stdlib/random.c
@@ -0,0 +1,446 @@
1/* $OpenBSD: random.c,v 1.19 2013/08/01 19:42:08 kettenis Exp $ */
2/*
3 * Copyright (c) 1983 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/param.h>
32#include <sys/sysctl.h>
33#include <sys/time.h>
34#include <fcntl.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38
39#include "thread_private.h"
40
41/*
42 * random.c:
43 *
44 * An improved random number generation package. In addition to the standard
45 * rand()/srand() like interface, this package also has a special state info
46 * interface. The initstate() routine is called with a seed, an array of
47 * bytes, and a count of how many bytes are being passed in; this array is
48 * then initialized to contain information for random number generation with
49 * that much state information. Good sizes for the amount of state
50 * information are 32, 64, 128, and 256 bytes. The state can be switched by
51 * calling the setstate() routine with the same array as was initiallized
52 * with initstate(). By default, the package runs with 128 bytes of state
53 * information and generates far better random numbers than a linear
54 * congruential generator. If the amount of state information is less than
55 * 32 bytes, a simple linear congruential R.N.G. is used.
56 *
57 * Internally, the state information is treated as an array of int32_t; the
58 * zeroeth element of the array is the type of R.N.G. being used (small
59 * integer); the remainder of the array is the state information for the
60 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
61 * state information, which will allow a degree seven polynomial. (Note:
62 * the zeroeth word of state information also has some other information
63 * stored in it -- see setstate() for details).
64 *
65 * The random number generation technique is a linear feedback shift register
66 * approach, employing trinomials (since there are fewer terms to sum up that
67 * way). In this approach, the least significant bit of all the numbers in
68 * the state table will act as a linear feedback shift register, and will
69 * have period 2^deg - 1 (where deg is the degree of the polynomial being
70 * used, assuming that the polynomial is irreducible and primitive). The
71 * higher order bits will have longer periods, since their values are also
72 * influenced by pseudo-random carries out of the lower bits. The total
73 * period of the generator is approximately deg*(2**deg - 1); thus doubling
74 * the amount of state information has a vast influence on the period of the
75 * generator. Note: the deg*(2**deg - 1) is an approximation only good for
76 * large deg, when the period of the shift register is the dominant factor.
77 * With deg equal to seven, the period is actually much longer than the
78 * 7*(2**7 - 1) predicted by this formula.
79 */
80
81/*
82 * For each of the currently supported random number generators, we have a
83 * break value on the amount of state information (you need at least this
84 * many bytes of state info to support this random number generator), a degree
85 * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
86 * the separation between the two lower order coefficients of the trinomial.
87 */
88#define TYPE_0 0 /* linear congruential */
89#define BREAK_0 8
90#define DEG_0 0
91#define SEP_0 0
92
93#define TYPE_1 1 /* x**7 + x**3 + 1 */
94#define BREAK_1 32
95#define DEG_1 7
96#define SEP_1 3
97
98#define TYPE_2 2 /* x**15 + x + 1 */
99#define BREAK_2 64
100#define DEG_2 15
101#define SEP_2 1
102
103#define TYPE_3 3 /* x**31 + x**3 + 1 */
104#define BREAK_3 128
105#define DEG_3 31
106#define SEP_3 3
107
108#define TYPE_4 4 /* x**63 + x + 1 */
109#define BREAK_4 256
110#define DEG_4 63
111#define SEP_4 1
112
113/*
114 * Array versions of the above information to make code run faster --
115 * relies on fact that TYPE_i == i.
116 */
117#define MAX_TYPES 5 /* max number of types above */
118
119static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
120static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
121
122/*
123 * Initially, everything is set up as if from:
124 *
125 * initstate(1, &randtbl, 128);
126 *
127 * Note that this initialization takes advantage of the fact that srandom()
128 * advances the front and rear pointers 10*rand_deg times, and hence the
129 * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
130 * element of the state information, which contains info about the current
131 * position of the rear pointer is just
132 *
133 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
134 */
135
136static int32_t randtbl[DEG_3 + 1] = {
137 TYPE_3,
138 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
139 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
140 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
141 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
142 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
143 0xf3bec5da,
144};
145
146/*
147 * fptr and rptr are two pointers into the state info, a front and a rear
148 * pointer. These two pointers are always rand_sep places aparts, as they
149 * cycle cyclically through the state information. (Yes, this does mean we
150 * could get away with just one pointer, but the code for random() is more
151 * efficient this way). The pointers are left positioned as they would be
152 * from the call
153 *
154 * initstate(1, randtbl, 128);
155 *
156 * (The position of the rear pointer, rptr, is really 0 (as explained above
157 * in the initialization of randtbl) because the state table pointer is set
158 * to point to randtbl[1] (as explained below).
159 */
160static int32_t *fptr = &randtbl[SEP_3 + 1];
161static int32_t *rptr = &randtbl[1];
162
163/*
164 * The following things are the pointer to the state information table, the
165 * type of the current generator, the degree of the current polynomial being
166 * used, and the separation between the two pointers. Note that for efficiency
167 * of random(), we remember the first location of the state information, not
168 * the zeroeth. Hence it is valid to access state[-1], which is used to
169 * store the type of the R.N.G. Also, we remember the last location, since
170 * this is more efficient than indexing every time to find the address of
171 * the last element to see if the front and rear pointers have wrapped.
172 */
173static int32_t *state = &randtbl[1];
174static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3;
176static int rand_deg = DEG_3;
177static int rand_sep = SEP_3;
178
179_THREAD_PRIVATE_MUTEX(random);
180static long random_l(void);
181
182#define LOCK() _THREAD_PRIVATE_MUTEX_LOCK(random)
183#define UNLOCK() _THREAD_PRIVATE_MUTEX_UNLOCK(random)
184
185/*
186 * srandom:
187 *
188 * Initialize the random number generator based on the given seed. If the
189 * type is the trivial no-state-information type, just remember the seed.
190 * Otherwise, initializes state[] based on the given "seed" via a linear
191 * congruential generator. Then, the pointers are set to known locations
192 * that are exactly rand_sep places apart. Lastly, it cycles the state
193 * information a given number of times to get rid of any initial dependencies
194 * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
195 * for default usage relies on values produced by this routine.
196 */
197static void
198srandom_l(unsigned int x)
199{
200 int i;
201 int32_t test;
202 div_t val;
203
204 if (rand_type == TYPE_0)
205 state[0] = x;
206 else {
207 /* A seed of 0 would result in state[] always being zero. */
208 state[0] = x ? x : 1;
209 for (i = 1; i < rand_deg; i++) {
210 /*
211 * Implement the following, without overflowing 31 bits:
212 *
213 * state[i] = (16807 * state[i - 1]) % 2147483647;
214 *
215 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
216 */
217 val = div(state[i-1], 127773);
218 test = 16807 * val.rem - 2836 * val.quot;
219 state[i] = test + (test < 0 ? 2147483647 : 0);
220 }
221 fptr = &state[rand_sep];
222 rptr = &state[0];
223 for (i = 0; i < 10 * rand_deg; i++)
224 (void)random_l();
225 }
226}
227
228void
229srandom(unsigned int x)
230{
231 LOCK();
232 srandom_l(x);
233 UNLOCK();
234}
235
236#if defined(APIWARN)
237__warn_references(srandom,
238 "warning: srandom() seed choices are invariably poor");
239#endif
240
241/*
242 * srandomdev:
243 *
244 * Many programs choose the seed value in a totally predictable manner.
245 * This often causes problems. We seed the generator using random
246 * data from the kernel.
247 * Note that this particular seeding procedure can generate states
248 * which are impossible to reproduce by calling srandom() with any
249 * value, since the succeeding terms in the state buffer are no longer
250 * derived from the LC algorithm applied to a fixed seed.
251 */
252void
253srandomdev(void)
254{
255 int mib[2];
256 size_t len;
257
258 LOCK();
259 if (rand_type == TYPE_0)
260 len = sizeof(state[0]);
261 else
262 len = rand_deg * sizeof(state[0]);
263
264 mib[0] = CTL_KERN;
265 mib[1] = KERN_ARND;
266 sysctl(mib, 2, state, &len, NULL, 0);
267
268 if (rand_type != TYPE_0) {
269 fptr = &state[rand_sep];
270 rptr = &state[0];
271 }
272 UNLOCK();
273}
274
275#if defined(APIWARN)
276__warn_references(srandomdev,
277 "warning: srandomdev() usage; consider switching to arc4random()");
278#endif
279
280/*
281 * initstate:
282 *
283 * Initialize the state information in the given array of n bytes for future
284 * random number generation. Based on the number of bytes we are given, and
285 * the break values for the different R.N.G.'s, we choose the best (largest)
286 * one we can and set things up for it. srandom() is then called to
287 * initialize the state information.
288 *
289 * Note that on return from srandom(), we set state[-1] to be the type
290 * multiplexed with the current value of the rear pointer; this is so
291 * successive calls to initstate() won't lose this information and will be
292 * able to restart with setstate().
293 *
294 * Note: the first thing we do is save the current state, if any, just like
295 * setstate() so that it doesn't matter when initstate is called.
296 *
297 * Returns a pointer to the old state.
298 */
299char *
300initstate(u_int seed, char *arg_state, size_t n)
301{
302 char *ostate = (char *)(&state[-1]);
303
304 LOCK();
305 if (rand_type == TYPE_0)
306 state[-1] = rand_type;
307 else
308 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
309 if (n < BREAK_0) {
310 UNLOCK();
311 return(NULL);
312 }
313 if (n < BREAK_1) {
314 rand_type = TYPE_0;
315 rand_deg = DEG_0;
316 rand_sep = SEP_0;
317 } else if (n < BREAK_2) {
318 rand_type = TYPE_1;
319 rand_deg = DEG_1;
320 rand_sep = SEP_1;
321 } else if (n < BREAK_3) {
322 rand_type = TYPE_2;
323 rand_deg = DEG_2;
324 rand_sep = SEP_2;
325 } else if (n < BREAK_4) {
326 rand_type = TYPE_3;
327 rand_deg = DEG_3;
328 rand_sep = SEP_3;
329 } else {
330 rand_type = TYPE_4;
331 rand_deg = DEG_4;
332 rand_sep = SEP_4;
333 }
334 state = &(((int32_t *)arg_state)[1]); /* first location */
335 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
336 srandom_l(seed);
337 if (rand_type == TYPE_0)
338 state[-1] = rand_type;
339 else
340 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
341 UNLOCK();
342 return(ostate);
343}
344
345/*
346 * setstate:
347 *
348 * Restore the state from the given state array.
349 *
350 * Note: it is important that we also remember the locations of the pointers
351 * in the current state information, and restore the locations of the pointers
352 * from the old state information. This is done by multiplexing the pointer
353 * location into the zeroeth word of the state information.
354 *
355 * Note that due to the order in which things are done, it is OK to call
356 * setstate() with the same state as the current state.
357 *
358 * Returns a pointer to the old state information.
359 */
360char *
361setstate(char *arg_state)
362{
363 int32_t *new_state = (int32_t *)arg_state;
364 int32_t type = new_state[0] % MAX_TYPES;
365 int32_t rear = new_state[0] / MAX_TYPES;
366 char *ostate = (char *)(&state[-1]);
367
368 LOCK();
369 if (rand_type == TYPE_0)
370 state[-1] = rand_type;
371 else
372 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
373 switch(type) {
374 case TYPE_0:
375 case TYPE_1:
376 case TYPE_2:
377 case TYPE_3:
378 case TYPE_4:
379 rand_type = type;
380 rand_deg = degrees[type];
381 rand_sep = seps[type];
382 break;
383 default:
384 UNLOCK();
385 return(NULL);
386 }
387 state = &new_state[1];
388 if (rand_type != TYPE_0) {
389 rptr = &state[rear];
390 fptr = &state[(rear + rand_sep) % rand_deg];
391 }
392 end_ptr = &state[rand_deg]; /* set end_ptr too */
393 UNLOCK();
394 return(ostate);
395}
396
397/*
398 * random:
399 *
400 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
401 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
402 * the same in all the other cases due to all the global variables that have
403 * been set up. The basic operation is to add the number at the rear pointer
404 * into the one at the front pointer. Then both pointers are advanced to
405 * the next location cyclically in the table. The value returned is the sum
406 * generated, reduced to 31 bits by throwing away the "least random" low bit.
407 *
408 * Note: the code takes advantage of the fact that both the front and
409 * rear pointers can't wrap on the same call by not testing the rear
410 * pointer if the front one has wrapped.
411 *
412 * Returns a 31-bit random number.
413 */
414static long
415random_l(void)
416{
417 int32_t i;
418
419 if (rand_type == TYPE_0)
420 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
421 else {
422 *fptr += *rptr;
423 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
424 if (++fptr >= end_ptr) {
425 fptr = state;
426 ++rptr;
427 } else if (++rptr >= end_ptr)
428 rptr = state;
429 }
430 return((long)i);
431}
432
433long
434random(void)
435{
436 long r;
437 LOCK();
438 r = random_l();
439 UNLOCK();
440 return r;
441}
442
443#if defined(APIWARN)
444__warn_references(random,
445 "warning: random() isn't random; consider using arc4random()");
446#endif
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000000..5966b38058
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.3
@@ -0,0 +1,130 @@
1.\" Copyright (c) 1994
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Jan-Simon Pendry.
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. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" $OpenBSD: realpath.3,v 1.19 2014/01/20 22:40:06 schwarze Exp $
32.\"
33.Dd $Mdocdate: January 20 2014 $
34.Dt REALPATH 3
35.Os
36.Sh NAME
37.Nm realpath
38.Nd returns the canonicalized absolute pathname
39.Sh SYNOPSIS
40.In limits.h
41.In stdlib.h
42.Ft "char *"
43.Fn realpath "const char *pathname" "char *resolved"
44.Sh DESCRIPTION
45The
46.Fn realpath
47function resolves all symbolic links, extra
48.Dq /
49characters and references to
50.Pa /./
51and
52.Pa /../
53in
54.Fa pathname ,
55and copies the resulting absolute pathname into the memory referenced by
56.Fa resolved .
57The
58.Fa resolved
59argument
60.Em must
61refer to a buffer capable of storing at least
62.Dv PATH_MAX
63characters, or be
64.Dv NULL .
65.Pp
66The
67.Fn realpath
68function will resolve both absolute and relative paths
69and return the absolute pathname corresponding to
70.Fa pathname .
71All but the last component of
72.Fa pathname
73must exist when
74.Fn realpath
75is called.
76.Sh RETURN VALUES
77The
78.Fn realpath
79function returns
80.Fa resolved
81on success.
82If
83.Fa resolved
84is
85.Dv NULL
86and no error occurred, then
87.Fn realpath
88returns a NUL-terminated string in a newly allocated buffer.
89If an error occurs,
90.Fn realpath
91returns
92.Dv NULL
93and the contents of
94.Fa resolved
95are undefined.
96.Sh ERRORS
97The function
98.Fn realpath
99may fail and set the external variable
100.Va errno
101for any of the errors specified for the library functions
102.Xr lstat 2 ,
103.Xr readlink 2 ,
104and
105.Xr getcwd 3 .
106.Sh SEE ALSO
107.Xr readlink 1 ,
108.Xr getcwd 3
109.Sh STANDARDS
110The
111.Fn realpath
112function conforms to
113.St -p1003.1-2008 .
114.Sh HISTORY
115The
116.Fn realpath
117function call first appeared in
118.Bx 4.4 .
119.Sh CAVEATS
120This implementation of
121.Fn realpath
122differs slightly from the Solaris implementation.
123The
124.Bx 4.4
125version always returns absolute pathnames,
126whereas the Solaris implementation will,
127under certain circumstances, return a relative
128.Fa resolved
129when given a relative
130.Fa pathname .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000000..e0f9b123b3
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.c
@@ -0,0 +1,214 @@
1/* $OpenBSD: realpath.c,v 1.16 2013/04/05 12:59:54 kurt Exp $ */
2/*
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The names of the authors may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/param.h>
31#include <sys/stat.h>
32
33#include <errno.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
38/* A slightly modified copy of this file exists in libexec/ld.so */
39
40/*
41 * char *realpath(const char *path, char resolved[PATH_MAX]);
42 *
43 * Find the real name of path, by removing all ".", ".." and symlink
44 * components. Returns (resolved) on success, or (NULL) on failure,
45 * in which case the path which caused trouble is left in (resolved).
46 */
47char *
48realpath(const char *path, char *resolved)
49{
50 struct stat sb;
51 char *p, *q, *s;
52 size_t left_len, resolved_len;
53 unsigned symlinks;
54 int serrno, slen, mem_allocated;
55 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
56
57 if (path[0] == '\0') {
58 errno = ENOENT;
59 return (NULL);
60 }
61
62 serrno = errno;
63
64 if (resolved == NULL) {
65 resolved = malloc(PATH_MAX);
66 if (resolved == NULL)
67 return (NULL);
68 mem_allocated = 1;
69 } else
70 mem_allocated = 0;
71
72 symlinks = 0;
73 if (path[0] == '/') {
74 resolved[0] = '/';
75 resolved[1] = '\0';
76 if (path[1] == '\0')
77 return (resolved);
78 resolved_len = 1;
79 left_len = strlcpy(left, path + 1, sizeof(left));
80 } else {
81 if (getcwd(resolved, PATH_MAX) == NULL) {
82 if (mem_allocated)
83 free(resolved);
84 else
85 strlcpy(resolved, ".", PATH_MAX);
86 return (NULL);
87 }
88 resolved_len = strlen(resolved);
89 left_len = strlcpy(left, path, sizeof(left));
90 }
91 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
92 errno = ENAMETOOLONG;
93 goto err;
94 }
95
96 /*
97 * Iterate over path components in `left'.
98 */
99 while (left_len != 0) {
100 /*
101 * Extract the next path component and adjust `left'
102 * and its length.
103 */
104 p = strchr(left, '/');
105 s = p ? p : left + left_len;
106 if (s - left >= sizeof(next_token)) {
107 errno = ENAMETOOLONG;
108 goto err;
109 }
110 memcpy(next_token, left, s - left);
111 next_token[s - left] = '\0';
112 left_len -= s - left;
113 if (p != NULL)
114 memmove(left, s + 1, left_len + 1);
115 if (resolved[resolved_len - 1] != '/') {
116 if (resolved_len + 1 >= PATH_MAX) {
117 errno = ENAMETOOLONG;
118 goto err;
119 }
120 resolved[resolved_len++] = '/';
121 resolved[resolved_len] = '\0';
122 }
123 if (next_token[0] == '\0')
124 continue;
125 else if (strcmp(next_token, ".") == 0)
126 continue;
127 else if (strcmp(next_token, "..") == 0) {
128 /*
129 * Strip the last path component except when we have
130 * single "/"
131 */
132 if (resolved_len > 1) {
133 resolved[resolved_len - 1] = '\0';
134 q = strrchr(resolved, '/') + 1;
135 *q = '\0';
136 resolved_len = q - resolved;
137 }
138 continue;
139 }
140
141 /*
142 * Append the next path component and lstat() it. If
143 * lstat() fails we still can return successfully if
144 * there are no more path components left.
145 */
146 resolved_len = strlcat(resolved, next_token, PATH_MAX);
147 if (resolved_len >= PATH_MAX) {
148 errno = ENAMETOOLONG;
149 goto err;
150 }
151 if (lstat(resolved, &sb) != 0) {
152 if (errno == ENOENT && p == NULL) {
153 errno = serrno;
154 return (resolved);
155 }
156 goto err;
157 }
158 if (S_ISLNK(sb.st_mode)) {
159 if (symlinks++ > MAXSYMLINKS) {
160 errno = ELOOP;
161 goto err;
162 }
163 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
164 if (slen < 0)
165 goto err;
166 symlink[slen] = '\0';
167 if (symlink[0] == '/') {
168 resolved[1] = 0;
169 resolved_len = 1;
170 } else if (resolved_len > 1) {
171 /* Strip the last path component. */
172 resolved[resolved_len - 1] = '\0';
173 q = strrchr(resolved, '/') + 1;
174 *q = '\0';
175 resolved_len = q - resolved;
176 }
177
178 /*
179 * If there are any path components left, then
180 * append them to symlink. The result is placed
181 * in `left'.
182 */
183 if (p != NULL) {
184 if (symlink[slen - 1] != '/') {
185 if (slen + 1 >= sizeof(symlink)) {
186 errno = ENAMETOOLONG;
187 goto err;
188 }
189 symlink[slen] = '/';
190 symlink[slen + 1] = 0;
191 }
192 left_len = strlcat(symlink, left, sizeof(symlink));
193 if (left_len >= sizeof(left)) {
194 errno = ENAMETOOLONG;
195 goto err;
196 }
197 }
198 left_len = strlcpy(left, symlink, sizeof(left));
199 }
200 }
201
202 /*
203 * Remove trailing slash except when the resolved pathname
204 * is a single "/".
205 */
206 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
207 resolved[resolved_len - 1] = '\0';
208 return (resolved);
209
210err:
211 if (mem_allocated)
212 free(resolved);
213 return (NULL);
214}
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..ae249ae053
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,44 @@
1/* $OpenBSD: remque.c,v 1.2 2005/08/08 08:05:37 espie Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <search.h>
32
33struct qelem {
34 struct qelem *q_forw;
35 struct qelem *q_back;
36};
37
38void
39remque(void *element)
40{
41 struct qelem *e = (struct qelem *) element;
42 e->q_forw->q_back = e->q_back;
43 e->q_back->q_forw = e->q_forw;
44}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
new file mode 100644
index 0000000000..583262f2d5
--- /dev/null
+++ b/src/lib/libc/stdlib/seed48.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: seed48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21unsigned short *
22seed48(unsigned short xseed[3])
23{
24 static unsigned short sseed[3];
25
26 sseed[0] = __rand48_seed[0];
27 sseed[1] = __rand48_seed[1];
28 sseed[2] = __rand48_seed[2];
29 __rand48_seed[0] = xseed[0];
30 __rand48_seed[1] = xseed[1];
31 __rand48_seed[2] = xseed[2];
32 __rand48_mult[0] = RAND48_MULT_0;
33 __rand48_mult[1] = RAND48_MULT_1;
34 __rand48_mult[2] = RAND48_MULT_2;
35 __rand48_add = RAND48_ADD;
36 return sseed;
37}
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
new file mode 100644
index 0000000000..9060fdba88
--- /dev/null
+++ b/src/lib/libc/stdlib/setenv.c
@@ -0,0 +1,180 @@
1/* $OpenBSD: setenv.c,v 1.14 2012/09/23 16:08:04 jeremy Exp $ */
2/*
3 * Copyright (c) 1987 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <errno.h>
32#include <stdlib.h>
33#include <string.h>
34
35char *__findenv(const char *name, int len, int *offset);
36
37extern char **environ;
38static char **lastenv; /* last value of environ */
39
40/*
41 * putenv --
42 * Add a name=value string directly to the environmental, replacing
43 * any current value.
44 */
45int
46putenv(char *str)
47{
48 char **P, *cp;
49 size_t cnt;
50 int offset = 0;
51
52 for (cp = str; *cp && *cp != '='; ++cp)
53 ;
54 if (*cp != '=') {
55 errno = EINVAL;
56 return (-1); /* missing `=' in string */
57 }
58
59 if (__findenv(str, (int)(cp - str), &offset) != NULL) {
60 environ[offset++] = str;
61 /* could be set multiple times */
62 while (__findenv(str, (int)(cp - str), &offset)) {
63 for (P = &environ[offset];; ++P)
64 if (!(*P = *(P + 1)))
65 break;
66 }
67 return (0);
68 }
69
70 /* create new slot for string */
71 for (P = environ; *P != NULL; P++)
72 ;
73 cnt = P - environ;
74 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
75 if (!P)
76 return (-1);
77 if (lastenv != environ)
78 memcpy(P, environ, cnt * sizeof(char *));
79 lastenv = environ = P;
80 environ[cnt] = str;
81 environ[cnt + 1] = NULL;
82 return (0);
83}
84
85/*
86 * setenv --
87 * Set the value of the environmental variable "name" to be
88 * "value". If rewrite is set, replace any current value.
89 */
90int
91setenv(const char *name, const char *value, int rewrite)
92{
93 char *C, **P;
94 const char *np;
95 int l_value, offset = 0;
96
97 if (!name || !*name) {
98 errno = EINVAL;
99 return (-1);
100 }
101 for (np = name; *np && *np != '='; ++np)
102 ;
103 if (*np) {
104 errno = EINVAL;
105 return (-1); /* has `=' in name */
106 }
107
108 l_value = strlen(value);
109 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
110 int tmpoff = offset + 1;
111 if (!rewrite)
112 return (0);
113#if 0 /* XXX - existing entry may not be writable */
114 if (strlen(C) >= l_value) { /* old larger; copy over */
115 while ((*C++ = *value++))
116 ;
117 return (0);
118 }
119#endif
120 /* could be set multiple times */
121 while (__findenv(name, (int)(np - name), &tmpoff)) {
122 for (P = &environ[tmpoff];; ++P)
123 if (!(*P = *(P + 1)))
124 break;
125 }
126 } else { /* create new slot */
127 size_t cnt;
128
129 for (P = environ; *P != NULL; P++)
130 ;
131 cnt = P - environ;
132 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
133 if (!P)
134 return (-1);
135 if (lastenv != environ)
136 memcpy(P, environ, cnt * sizeof(char *));
137 lastenv = environ = P;
138 offset = cnt;
139 environ[cnt + 1] = NULL;
140 }
141 if (!(environ[offset] = /* name + `=' + value */
142 malloc((size_t)((int)(np - name) + l_value + 2))))
143 return (-1);
144 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
145 ;
146 for (*C++ = '='; (*C++ = *value++); )
147 ;
148 return (0);
149}
150
151/*
152 * unsetenv(name) --
153 * Delete environmental variable "name".
154 */
155int
156unsetenv(const char *name)
157{
158 char **P;
159 const char *np;
160 int offset = 0;
161
162 if (!name || !*name) {
163 errno = EINVAL;
164 return (-1);
165 }
166 for (np = name; *np && *np != '='; ++np)
167 ;
168 if (*np) {
169 errno = EINVAL;
170 return (-1); /* has `=' in name */
171 }
172
173 /* could be set multiple times */
174 while (__findenv(name, (int)(np - name), &offset)) {
175 for (P = &environ[offset];; ++P)
176 if (!(*P = *(P + 1)))
177 break;
178 }
179 return (0);
180}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
new file mode 100644
index 0000000000..f76b6cca86
--- /dev/null
+++ b/src/lib/libc/stdlib/srand48.c
@@ -0,0 +1,31 @@
1/* $OpenBSD: srand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21void
22srand48(long seed)
23{
24 __rand48_seed[0] = RAND48_SEED_0;
25 __rand48_seed[1] = (unsigned short) seed;
26 __rand48_seed[2] = (unsigned short) (seed >> 16);
27 __rand48_mult[0] = RAND48_MULT_0;
28 __rand48_mult[1] = RAND48_MULT_1;
29 __rand48_mult[2] = RAND48_MULT_2;
30 __rand48_add = RAND48_ADD;
31}
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
new file mode 100644
index 0000000000..6f079b73a9
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.3
@@ -0,0 +1,167 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: strtod.3,v 1.19 2014/01/19 10:39:00 schwarze Exp $
33.\"
34.Dd $Mdocdate: January 19 2014 $
35.Dt STRTOD 3
36.Os
37.Sh NAME
38.Nm strtod ,
39.Nm strtof ,
40.Nm strtold
41.Nd convert ASCII string to double, float or long double
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft double
45.Fn strtod "const char *nptr" "char **endptr"
46.Pp
47.Ft float
48.Fn strtof "const char *nptr" "char **endptr"
49.Pp
50.Ft long double
51.Fn strtold "const char *nptr" "char **endptr"
52.Sh DESCRIPTION
53The
54.Fn strtod
55function converts the initial portion of the string pointed to by
56.Fa nptr
57to
58.Li double
59representation.
60The
61.Fn strtof
62function converts the initial portion of the string pointed to by
63.Fa nptr
64to
65.Li float
66representation.
67The
68.Fn strtold
69function converts the initial portion of the string pointed to by
70.Fa nptr
71to
72.Li long double
73representation.
74.Pp
75The expected form of the string is an optional plus
76.Pq Ql +
77or minus sign
78.Pq Ql -
79followed by a sequence of digits optionally containing
80a decimal-point character, optionally followed by an exponent.
81An exponent consists of an
82.Sq E
83or
84.Sq e ,
85followed by an optional plus or minus sign, followed by a sequence of digits.
86.Pp
87Alternatively, if the portion of the string following the optional
88plus or minus sign begins with
89.Dq INF
90or
91.Dq NAN ,
92ignoring case, it is interpreted as an infinity or a quiet \*(Na,
93respectively.
94The syntax
95.Dq NAN Ns Pq Ar s ,
96where
97.Ar s
98is an alphanumeric string, produces the same value as the call
99.Fo nan
100.Qq Ar s Ns
101.Fc
102(respectively,
103.Fo nanf
104.Qq Ar s Ns
105.Fc
106and
107.Fo nanl
108.Qq Ar s Ns
109.Fc . )
110.Pp
111In any of the above cases, leading whitespace characters in the
112string (as defined by the
113.Xr isspace 3
114function) are skipped.
115.Sh RETURN VALUES
116The
117.Fn strtod ,
118.Fn strtof
119and
120.Fn strtold
121functions return the converted value, if any.
122.Pp
123If
124.Fa endptr
125is not
126.Dv NULL ,
127a pointer to the character after the last character used
128in the conversion is stored in the location referenced by
129.Fa endptr .
130.Pp
131If no conversion is performed, zero is returned and the value of
132.Fa nptr
133is stored in the location referenced by
134.Fa endptr .
135.Pp
136If the correct value would cause overflow, plus or minus
137.Dv HUGE_VAL
138is returned (according to the sign of the value), and
139.Er ERANGE
140is stored in
141.Va errno .
142If the correct value would cause underflow, zero is returned and
143.Er ERANGE
144is stored in
145.Va errno .
146.Sh ERRORS
147.Bl -tag -width Er
148.It Bq Er ERANGE
149Overflow or underflow occurred.
150.El
151.Sh SEE ALSO
152.Xr atof 3 ,
153.Xr atoi 3 ,
154.Xr atol 3 ,
155.Xr strtol 3 ,
156.Xr strtoul 3
157.Sh STANDARDS
158The
159.Fn strtod
160function conforms to
161.St -ansiC-89 .
162The
163.Fn strtof
164and
165.Fn strtold
166functions conform to
167.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/strtoimax.c b/src/lib/libc/stdlib/strtoimax.c
new file mode 100644
index 0000000000..2c77f41650
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoimax.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: strtoimax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35
36/*
37 * Convert a string to an intmax_t
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42intmax_t
43strtoimax(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 intmax_t acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * Skip white space and pick up leading +/- sign if any.
52 * If base is 0, allow 0x for hex and 0 for octal, else
53 * assume decimal; if base is already 16, allow 0x.
54 */
55 s = nptr;
56 do {
57 c = (unsigned char) *s++;
58 } while (isspace(c));
59 if (c == '-') {
60 neg = 1;
61 c = *s++;
62 } else {
63 neg = 0;
64 if (c == '+')
65 c = *s++;
66 }
67 if ((base == 0 || base == 16) &&
68 c == '0' && (*s == 'x' || *s == 'X')) {
69 c = s[1];
70 s += 2;
71 base = 16;
72 }
73 if (base == 0)
74 base = c == '0' ? 8 : 10;
75
76 /*
77 * Compute the cutoff value between legal numbers and illegal
78 * numbers. That is the largest legal value, divided by the
79 * base. An input number that is greater than this value, if
80 * followed by a legal input character, is too big. One that
81 * is equal to this value may be valid or not; the limit
82 * between valid and invalid numbers is then based on the last
83 * digit. For instance, if the range for intmax_t is
84 * [-9223372036854775808..9223372036854775807] and the input base
85 * is 10, cutoff will be set to 922337203685477580 and cutlim to
86 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
87 * accumulated a value > 922337203685477580, or equal but the
88 * next digit is > 7 (or 8), the number is too big, and we will
89 * return a range error.
90 *
91 * Set any if any `digits' consumed; make it negative to indicate
92 * overflow.
93 */
94 cutoff = neg ? INTMAX_MIN : INTMAX_MAX;
95 cutlim = cutoff % base;
96 cutoff /= base;
97 if (neg) {
98 if (cutlim > 0) {
99 cutlim -= base;
100 cutoff += 1;
101 }
102 cutlim = -cutlim;
103 }
104 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
105 if (isdigit(c))
106 c -= '0';
107 else if (isalpha(c))
108 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
109 else
110 break;
111 if (c >= base)
112 break;
113 if (any < 0)
114 continue;
115 if (neg) {
116 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
117 any = -1;
118 acc = INTMAX_MIN;
119 errno = ERANGE;
120 } else {
121 any = 1;
122 acc *= base;
123 acc -= c;
124 }
125 } else {
126 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
127 any = -1;
128 acc = INTMAX_MAX;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc += c;
134 }
135 }
136 }
137 if (endptr != 0)
138 *endptr = (char *) (any ? s - 1 : nptr);
139 return (acc);
140}
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
new file mode 100644
index 0000000000..c0a60979d9
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.3
@@ -0,0 +1,264 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: strtol.3,v 1.24 2013/08/14 06:32:28 jmc Exp $
33.\"
34.Dd $Mdocdate: August 14 2013 $
35.Dt STRTOL 3
36.Os
37.Sh NAME
38.Nm strtol ,
39.Nm strtoll ,
40.Nm strtoimax ,
41.Nm strtoq ,
42.Nd convert string value to a long, long long or intmax_t integer
43.Sh SYNOPSIS
44.In limits.h
45.In stdlib.h
46.Ft long
47.Fn strtol "const char *nptr" "char **endptr" "int base"
48.Pp
49.Ft long long
50.Fn strtoll "const char *nptr" "char **endptr" "int base"
51.Pp
52.In inttypes.h
53.Ft intmax_t
54.Fn strtoimax "const char *nptr" "char **endptr" "int base"
55.Pp
56.In sys/types.h
57.In limits.h
58.In stdlib.h
59.Ft quad_t
60.Fn strtoq "const char *nptr" "char **endptr" "int base"
61.Sh DESCRIPTION
62The
63.Fn strtol
64function converts the string in
65.Fa nptr
66to a
67.Li long
68value.
69The
70.Fn strtoll
71function converts the string in
72.Fa nptr
73to a
74.Li long long
75value.
76The
77.Fn strtoimax
78function converts the string in
79.Fa nptr
80to an
81.Li intmax_t
82value.
83The
84.Fn strtoq
85function is a deprecated equivalent of
86.Fn strtoll
87and is provided for backwards compatibility with legacy programs.
88The conversion is done according to the given
89.Fa base ,
90which must be a number between 2 and 36 inclusive or the special value 0.
91.Pp
92The string may begin with an arbitrary amount of whitespace
93(as determined by
94.Xr isspace 3 )
95followed by a single optional
96.Ql +
97or
98.Ql -
99sign.
100If
101.Fa base
102is zero or 16, the string may then include a
103.Ql 0x
104prefix, and the number will be read in base 16; otherwise, a zero
105.Fa base
106is taken as 10 (decimal) unless the next character is
107.Ql 0 ,
108in which case it is taken as 8 (octal).
109.Pp
110The remainder of the string is converted to a
111.Li long ,
112.Li long long ,
113or
114.Li intmax_t ,
115value in the obvious manner,
116stopping at the first character which is not a valid digit
117in the given base.
118(In bases above 10, the letter
119.Ql A
120in either upper or lower case represents 10,
121.Ql B
122represents 11, and so forth, with
123.Ql Z
124representing 35.)
125.Pp
126If
127.Fa endptr
128is non-null,
129.Fn strtol
130stores the address of the first invalid character in
131.Fa *endptr .
132If there were no digits at all, however,
133.Fn strtol
134stores the original value of
135.Fa nptr
136in
137.Fa *endptr .
138(Thus, if
139.Fa *nptr
140is not
141.Ql \e0
142but
143.Fa **endptr
144is
145.Ql \e0
146on return, the entire string was valid.)
147.Sh RETURN VALUES
148The
149.Fn strtol ,
150.Fn strtoll ,
151.Fn strtoimax ,
152and
153.Fn strtoq
154functions return the result of the conversion,
155unless the value would underflow or overflow.
156If no conversion could be performed, 0 is returned;
157the global variable
158.Va errno
159is also set to
160.Er EINVAL ,
161though this is not portable across all platforms.
162If overflow or underflow occurs,
163.Va errno
164is set to
165.Er ERANGE
166and the function return value is as follows:
167.Bl -column "strtoimaxXX" "INTMAX_MIN" "INTMAX_MAX" -offset indent
168.It Sy Function Ta Sy underflow Ta Sy overflow
169.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
170.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
171.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
172.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX
173.El
174.Sh EXAMPLES
175Ensuring that a string is a valid number (i.e., in range and containing no
176trailing characters) requires clearing
177.Va errno
178beforehand explicitly since
179.Va errno
180is not changed on a successful call to
181.Fn strtol ,
182and the return value of
183.Fn strtol
184cannot be used unambiguously to signal an error:
185.Bd -literal -offset indent
186char *ep;
187long lval;
188
189\&...
190
191errno = 0;
192lval = strtol(buf, &ep, 10);
193if (buf[0] == '\e0' || *ep != '\e0')
194 goto not_a_number;
195if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
196 goto out_of_range;
197.Ed
198.Pp
199This example will accept
200.Dq 12
201but not
202.Dq 12foo
203or
204.Dq 12\en .
205If trailing whitespace is acceptable, further checks must be done on
206.Va *ep ;
207alternately, use
208.Xr sscanf 3 .
209.Pp
210If
211.Fn strtol
212is being used instead of
213.Xr atoi 3 ,
214error checking is further complicated because the desired return value is an
215.Li int
216rather than a
217.Li long ;
218however, on some architectures integers and long integers are the same size.
219Thus the following is necessary:
220.Bd -literal -offset indent
221char *ep;
222int ival;
223long lval;
224
225\&...
226
227errno = 0;
228lval = strtol(buf, &ep, 10);
229if (buf[0] == '\e0' || *ep != '\e0')
230 goto not_a_number;
231if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
232 (lval > INT_MAX || lval < INT_MIN))
233 goto out_of_range;
234ival = lval;
235.Ed
236.Sh ERRORS
237.Bl -tag -width Er
238.It Bq Er ERANGE
239The given string was out of range; the value converted has been clamped.
240.El
241.Sh SEE ALSO
242.Xr atof 3 ,
243.Xr atoi 3 ,
244.Xr atol 3 ,
245.Xr atoll 3 ,
246.Xr sscanf 3 ,
247.Xr strtod 3 ,
248.Xr strtonum 3 ,
249.Xr strtoul 3
250.Sh STANDARDS
251The
252.Fn strtol ,
253.Fn strtoll ,
254and
255.Fn strtoimax
256functions conform to
257.St -ansiC-99 .
258The
259.Fn strtoq
260function is a
261.Bx
262extension and is provided for backwards compatibility with legacy programs.
263.Sh BUGS
264Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
new file mode 100644
index 0000000000..dc2cf8871c
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.c
@@ -0,0 +1,151 @@
1/* $OpenBSD: strtol.c,v 1.9 2013/04/17 17:40:35 tedu Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <ctype.h>
32#include <errno.h>
33#include <limits.h>
34#include <stdlib.h>
35
36
37/*
38 * Convert a string to a long integer.
39 *
40 * Ignores `locale' stuff. Assumes that the upper and lower case
41 * alphabets and digits are each contiguous.
42 */
43long
44strtol(const char *nptr, char **endptr, int base)
45{
46 const char *s;
47 long acc, cutoff;
48 int c;
49 int neg, any, cutlim;
50
51 /*
52 * Ensure that base is between 2 and 36 inclusive, or the special
53 * value of 0.
54 */
55 if (base != 0 && (base < 2 || base > 36)) {
56 if (endptr != 0)
57 *endptr = (char *)nptr;
58 errno = EINVAL;
59 return 0;
60 }
61
62 /*
63 * Skip white space and pick up leading +/- sign if any.
64 * If base is 0, allow 0x for hex and 0 for octal, else
65 * assume decimal; if base is already 16, allow 0x.
66 */
67 s = nptr;
68 do {
69 c = (unsigned char) *s++;
70 } while (isspace(c));
71 if (c == '-') {
72 neg = 1;
73 c = *s++;
74 } else {
75 neg = 0;
76 if (c == '+')
77 c = *s++;
78 }
79 if ((base == 0 || base == 16) &&
80 c == '0' && (*s == 'x' || *s == 'X')) {
81 c = s[1];
82 s += 2;
83 base = 16;
84 }
85 if (base == 0)
86 base = c == '0' ? 8 : 10;
87
88 /*
89 * Compute the cutoff value between legal numbers and illegal
90 * numbers. That is the largest legal value, divided by the
91 * base. An input number that is greater than this value, if
92 * followed by a legal input character, is too big. One that
93 * is equal to this value may be valid or not; the limit
94 * between valid and invalid numbers is then based on the last
95 * digit. For instance, if the range for longs is
96 * [-2147483648..2147483647] and the input base is 10,
97 * cutoff will be set to 214748364 and cutlim to either
98 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
99 * a value > 214748364, or equal but the next digit is > 7 (or 8),
100 * the number is too big, and we will return a range error.
101 *
102 * Set any if any `digits' consumed; make it negative to indicate
103 * overflow.
104 */
105 cutoff = neg ? LONG_MIN : LONG_MAX;
106 cutlim = cutoff % base;
107 cutoff /= base;
108 if (neg) {
109 if (cutlim > 0) {
110 cutlim -= base;
111 cutoff += 1;
112 }
113 cutlim = -cutlim;
114 }
115 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
116 if (isdigit(c))
117 c -= '0';
118 else if (isalpha(c))
119 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
120 else
121 break;
122 if (c >= base)
123 break;
124 if (any < 0)
125 continue;
126 if (neg) {
127 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
128 any = -1;
129 acc = LONG_MIN;
130 errno = ERANGE;
131 } else {
132 any = 1;
133 acc *= base;
134 acc -= c;
135 }
136 } else {
137 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
138 any = -1;
139 acc = LONG_MAX;
140 errno = ERANGE;
141 } else {
142 any = 1;
143 acc *= base;
144 acc += c;
145 }
146 }
147 }
148 if (endptr != 0)
149 *endptr = (char *) (any ? s - 1 : nptr);
150 return (acc);
151}
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000000..4bcc5565be
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,144 @@
1/* $OpenBSD: strtoll.c,v 1.7 2013/03/28 18:09:38 martynas Exp $ */
2/*-
3 * Copyright (c) 1992 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32
33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
36#include <stdlib.h>
37
38/*
39 * Convert a string to a long long.
40 *
41 * Ignores `locale' stuff. Assumes that the upper and lower case
42 * alphabets and digits are each contiguous.
43 */
44long long
45strtoll(const char *nptr, char **endptr, int base)
46{
47 const char *s;
48 long long acc, cutoff;
49 int c;
50 int neg, any, cutlim;
51
52 /*
53 * Skip white space and pick up leading +/- sign if any.
54 * If base is 0, allow 0x for hex and 0 for octal, else
55 * assume decimal; if base is already 16, allow 0x.
56 */
57 s = nptr;
58 do {
59 c = (unsigned char) *s++;
60 } while (isspace(c));
61 if (c == '-') {
62 neg = 1;
63 c = *s++;
64 } else {
65 neg = 0;
66 if (c == '+')
67 c = *s++;
68 }
69 if ((base == 0 || base == 16) &&
70 c == '0' && (*s == 'x' || *s == 'X')) {
71 c = s[1];
72 s += 2;
73 base = 16;
74 }
75 if (base == 0)
76 base = c == '0' ? 8 : 10;
77
78 /*
79 * Compute the cutoff value between legal numbers and illegal
80 * numbers. That is the largest legal value, divided by the
81 * base. An input number that is greater than this value, if
82 * followed by a legal input character, is too big. One that
83 * is equal to this value may be valid or not; the limit
84 * between valid and invalid numbers is then based on the last
85 * digit. For instance, if the range for long longs is
86 * [-9223372036854775808..9223372036854775807] and the input base
87 * is 10, cutoff will be set to 922337203685477580 and cutlim to
88 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
89 * accumulated a value > 922337203685477580, or equal but the
90 * next digit is > 7 (or 8), the number is too big, and we will
91 * return a range error.
92 *
93 * Set any if any `digits' consumed; make it negative to indicate
94 * overflow.
95 */
96 cutoff = neg ? LLONG_MIN : LLONG_MAX;
97 cutlim = cutoff % base;
98 cutoff /= base;
99 if (neg) {
100 if (cutlim > 0) {
101 cutlim -= base;
102 cutoff += 1;
103 }
104 cutlim = -cutlim;
105 }
106 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
107 if (isdigit(c))
108 c -= '0';
109 else if (isalpha(c))
110 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
111 else
112 break;
113 if (c >= base)
114 break;
115 if (any < 0)
116 continue;
117 if (neg) {
118 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
119 any = -1;
120 acc = LLONG_MIN;
121 errno = ERANGE;
122 } else {
123 any = 1;
124 acc *= base;
125 acc -= c;
126 }
127 } else {
128 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
129 any = -1;
130 acc = LLONG_MAX;
131 errno = ERANGE;
132 } else {
133 any = 1;
134 acc *= base;
135 acc += c;
136 }
137 }
138 }
139 if (endptr != 0)
140 *endptr = (char *) (any ? s - 1 : nptr);
141 return (acc);
142}
143
144__strong_alias(strtoq, strtoll);
diff --git a/src/lib/libc/stdlib/strtonum.3 b/src/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000000..ed638cdbe2
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,152 @@
1.\" $OpenBSD: strtonum.3,v 1.17 2013/08/14 06:32:28 jmc Exp $
2.\"
3.\" Copyright (c) 2004 Ted Unangst
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: August 14 2013 $
18.Dt STRTONUM 3
19.Os
20.Sh NAME
21.Nm strtonum
22.Nd reliably convert string value to an integer
23.Sh SYNOPSIS
24.In stdlib.h
25.Ft long long
26.Fo strtonum
27.Fa "const char *nptr"
28.Fa "long long minval"
29.Fa "long long maxval"
30.Fa "const char **errstr"
31.Fc
32.Sh DESCRIPTION
33The
34.Fn strtonum
35function converts the string in
36.Fa nptr
37to a
38.Li long long
39value.
40The
41.Fn strtonum
42function was designed to facilitate safe, robust programming
43and overcome the shortcomings of the
44.Xr atoi 3
45and
46.Xr strtol 3
47family of interfaces.
48.Pp
49The string may begin with an arbitrary amount of whitespace
50(as determined by
51.Xr isspace 3 )
52followed by a single optional
53.Ql +
54or
55.Ql -
56sign.
57.Pp
58The remainder of the string is converted to a
59.Li long long
60value according to base 10.
61.Pp
62The value obtained is then checked against the provided
63.Fa minval
64and
65.Fa maxval
66bounds.
67If
68.Fa errstr
69is non-null,
70.Fn strtonum
71stores an error string in
72.Fa *errstr
73indicating the failure.
74.Sh RETURN VALUES
75The
76.Fn strtonum
77function returns the result of the conversion,
78unless the value would exceed the provided bounds or is invalid.
79On error, 0 is returned,
80.Va errno
81is set, and
82.Fa errstr
83will point to an error message.
84.Fa *errstr
85will be set to
86.Dv NULL
87on success;
88this fact can be used to differentiate
89a successful return of 0 from an error.
90.Sh EXAMPLES
91Using
92.Fn strtonum
93correctly is meant to be simpler than the alternative functions.
94.Bd -literal -offset indent
95int iterations;
96const char *errstr;
97
98iterations = strtonum(optarg, 1, 64, &errstr);
99if (errstr)
100 errx(1, "number of iterations is %s: %s", errstr, optarg);
101.Ed
102.Pp
103The above example will guarantee that the value of iterations is between
1041 and 64 (inclusive).
105.Sh ERRORS
106.Bl -tag -width Er
107.It Bq Er ERANGE
108The given string was out of range.
109.It Bq Er EINVAL
110The given string did not consist solely of digit characters.
111.It Bq Er EINVAL
112.Ar minval
113was larger than
114.Ar maxval .
115.El
116.Pp
117If an error occurs,
118.Fa errstr
119will be set to one of the following strings:
120.Pp
121.Bl -tag -width "too largeXX" -compact
122.It Qq too large
123The result was larger than the provided maximum value.
124.It Qq too small
125The result was smaller than the provided minimum value.
126.It Qq invalid
127The string did not consist solely of digit characters.
128.El
129.Sh SEE ALSO
130.Xr atof 3 ,
131.Xr atoi 3 ,
132.Xr atol 3 ,
133.Xr atoll 3 ,
134.Xr sscanf 3 ,
135.Xr strtod 3 ,
136.Xr strtol 3 ,
137.Xr strtoul 3
138.Sh STANDARDS
139.Fn strtonum
140is an
141.Ox
142extension.
143The existing alternatives, such as
144.Xr atoi 3
145and
146.Xr strtol 3 ,
147are either impossible or difficult to use safely.
148.Sh HISTORY
149The
150.Fn strtonum
151function first appeared in
152.Ox 3.6 .
diff --git a/src/lib/libc/stdlib/strtonum.c b/src/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000000..1aeee3467b
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,65 @@
1/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */
2
3/*
4 * Copyright (c) 2004 Ted Unangst and Todd Miller
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <errno.h>
21#include <limits.h>
22#include <stdlib.h>
23
24#define INVALID 1
25#define TOOSMALL 2
26#define TOOLARGE 3
27
28long long
29strtonum(const char *numstr, long long minval, long long maxval,
30 const char **errstrp)
31{
32 long long ll = 0;
33 int error = 0;
34 char *ep;
35 struct errval {
36 const char *errstr;
37 int err;
38 } ev[4] = {
39 { NULL, 0 },
40 { "invalid", EINVAL },
41 { "too small", ERANGE },
42 { "too large", ERANGE },
43 };
44
45 ev[0].err = errno;
46 errno = 0;
47 if (minval > maxval) {
48 error = INVALID;
49 } else {
50 ll = strtoll(numstr, &ep, 10);
51 if (numstr == ep || *ep != '\0')
52 error = INVALID;
53 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54 error = TOOSMALL;
55 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56 error = TOOLARGE;
57 }
58 if (errstrp != NULL)
59 *errstrp = ev[error].errstr;
60 errno = ev[error].err;
61 if (error)
62 ll = 0;
63
64 return (ll);
65}
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
new file mode 100644
index 0000000000..1353637d68
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,245 @@
1.\" Copyright (c) 1990, 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.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information 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. 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.\" $OpenBSD: strtoul.3,v 1.22 2013/08/14 06:32:28 jmc Exp $
33.\"
34.Dd $Mdocdate: August 14 2013 $
35.Dt STRTOUL 3
36.Os
37.Sh NAME
38.Nm strtoul ,
39.Nm strtoull ,
40.Nm strtoumax ,
41.Nm strtouq
42.Nd convert a string to an unsigned long, unsigned long long or uintmax_t integer
43.Sh SYNOPSIS
44.In limits.h
45.In stdlib.h
46.Ft unsigned long
47.Fn strtoul "const char *nptr" "char **endptr" "int base"
48.Ft unsigned long long
49.Fn strtoull "const char *nptr" "char **endptr" "int base"
50.In inttypes.h
51.Ft uintmax_t
52.Fn strtoumax "const char *nptr" "char **endptr" "int base"
53.In sys/types.h
54.In limits.h
55.In stdlib.h
56.Ft u_quad_t
57.Fn strtouq "const char *nptr" "char **endptr" "int base"
58.Sh DESCRIPTION
59The
60.Fn strtoul
61function converts the string in
62.Fa nptr
63to an
64.Li unsigned long
65value.
66The
67.Fn strtoull
68function converts the string in
69.Fa nptr
70to an
71.Li unsigned long long
72value.
73The
74.Fn strtoumax
75function converts the string in
76.Fa nptr
77to a
78.Li umaxint_t
79value.
80The
81.Fn strtouq
82function is a deprecated equivalent of
83.Fn strtoull
84and is provided for backwards compatibility with legacy programs.
85The conversion is done according to the given
86.Fa base ,
87which must be a number between 2 and 36 inclusive
88or the special value 0.
89If the string in
90.Fa nptr
91represents a negative number, it will be converted to its unsigned equivalent.
92This behavior is consistent with what happens when a signed integer type is
93cast to its unsigned counterpart.
94.Pp
95The string may begin with an arbitrary amount of whitespace
96(as determined by
97.Xr isspace 3 )
98followed by a single optional
99.Ql +
100or
101.Ql -
102sign.
103If
104.Fa base
105is zero or 16, the string may then include a
106.Ql 0x
107prefix, and the number will be read in base 16; otherwise, a zero
108.Fa base
109is taken as 10 (decimal) unless the next character is
110.Ql 0 ,
111in which case it is taken as 8 (octal).
112.Pp
113The remainder of the string is converted to an
114.Li unsigned long
115value in the obvious manner, stopping at the end of the string
116or at the first character that does not produce a valid digit
117in the given base.
118(In bases above 10, the letter
119.Ql A
120in either upper or lower case represents 10,
121.Ql B
122represents 11, and so forth, with
123.Ql Z
124representing 35.)
125.Pp
126If
127.Fa endptr
128is non-null,
129.Fn strtoul
130stores the address of the first invalid character in
131.Fa *endptr .
132If there were no digits at all, however,
133.Fn strtoul
134stores the original value of
135.Fa nptr
136in
137.Fa *endptr .
138(Thus, if
139.Fa *nptr
140is not
141.Ql \e0
142but
143.Fa **endptr
144is
145.Ql \e0
146on return, the entire string was valid.)
147.Sh RETURN VALUES
148The
149.Fn strtoul ,
150.Fn strtoull ,
151.Fn strtoumax
152and
153.Fn strtouq
154functions return either the result of the conversion or,
155if there was a leading minus sign,
156the negation of the result of the conversion,
157unless the original (non-negated) value would overflow.
158If overflow occurs,
159.Fn strtoul
160returns
161.Dv ULONG_MAX ,
162.Fn strtoull
163returns
164.Dv ULLONG_MAX ,
165.Fn strtoumax
166returns
167.Dv UINTMAX_MAX ,
168.Fn strtouq
169returns
170.Dv ULLONG_MAX
171and the global variable
172.Va errno
173is set to
174.Er ERANGE .
175If no conversion could be performed, 0 is returned;
176the global variable
177.Va errno
178is also set to
179.Er EINVAL ,
180though this is not portable across all platforms.
181.Pp
182There is no way to determine if
183.Fn strtoul
184has processed a negative number (and returned an unsigned value) short of
185examining the string in
186.Fa nptr
187directly.
188.Sh EXAMPLES
189Ensuring that a string is a valid number (i.e., in range and containing no
190trailing characters) requires clearing
191.Va errno
192beforehand explicitly since
193.Va errno
194is not changed on a successful call to
195.Fn strtoul ,
196and the return value of
197.Fn strtoul
198cannot be used unambiguously to signal an error:
199.Bd -literal -offset indent
200char *ep;
201unsigned long ulval;
202
203\&...
204
205errno = 0;
206ulval = strtoul(buf, &ep, 10);
207if (buf[0] == '\e0' || *ep != '\e0')
208 goto not_a_number;
209if (errno == ERANGE && ulval == ULONG_MAX)
210 goto out_of_range;
211.Ed
212.Pp
213This example will accept
214.Dq 12
215but not
216.Dq 12foo
217or
218.Dq 12\en .
219If trailing whitespace is acceptable, further checks must be done on
220.Va *ep ;
221alternately, use
222.Xr sscanf 3 .
223.Sh ERRORS
224.Bl -tag -width Er
225.It Bq Er ERANGE
226The given string was out of range; the value converted has been clamped.
227.El
228.Sh SEE ALSO
229.Xr sscanf 3 ,
230.Xr strtol 3
231.Sh STANDARDS
232The
233.Fn strtoul ,
234.Fn strtoull ,
235and
236.Fn strtoumax
237functions conform to
238.St -ansiC-99 .
239The
240.Fn strtouq
241function is a
242.Bx
243extension and is provided for backwards compatibility with legacy programs.
244.Sh BUGS
245Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
new file mode 100644
index 0000000000..a236365d2f
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: strtoul.c,v 1.8 2013/04/17 17:40:35 tedu Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <ctype.h>
32#include <errno.h>
33#include <limits.h>
34#include <stdlib.h>
35
36/*
37 * Convert a string to an unsigned long integer.
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42unsigned long
43strtoul(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 unsigned long acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * See strtol for comments as to the logic used.
52 */
53 s = nptr;
54 do {
55 c = (unsigned char) *s++;
56 } while (isspace(c));
57 if (c == '-') {
58 neg = 1;
59 c = *s++;
60 } else {
61 neg = 0;
62 if (c == '+')
63 c = *s++;
64 }
65 if ((base == 0 || base == 16) &&
66 c == '0' && (*s == 'x' || *s == 'X')) {
67 c = s[1];
68 s += 2;
69 base = 16;
70 }
71 if (base == 0)
72 base = c == '0' ? 8 : 10;
73
74 cutoff = ULONG_MAX / (unsigned long)base;
75 cutlim = ULONG_MAX % (unsigned long)base;
76 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
77 if (isdigit(c))
78 c -= '0';
79 else if (isalpha(c))
80 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
81 else
82 break;
83 if (c >= base)
84 break;
85 if (any < 0)
86 continue;
87 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
88 any = -1;
89 acc = ULONG_MAX;
90 errno = ERANGE;
91 } else {
92 any = 1;
93 acc *= (unsigned long)base;
94 acc += c;
95 }
96 }
97 if (neg && any > 0)
98 acc = -acc;
99 if (endptr != 0)
100 *endptr = (char *) (any ? s - 1 : nptr);
101 return (acc);
102}
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000000..28f613a087
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: strtoull.c,v 1.6 2013/03/28 18:09:38 martynas Exp $ */
2/*-
3 * Copyright (c) 1992 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32
33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
36#include <stdlib.h>
37
38/*
39 * Convert a string to an unsigned long long.
40 *
41 * Ignores `locale' stuff. Assumes that the upper and lower case
42 * alphabets and digits are each contiguous.
43 */
44unsigned long long
45strtoull(const char *nptr, char **endptr, int base)
46{
47 const char *s;
48 unsigned long long acc, cutoff;
49 int c;
50 int neg, any, cutlim;
51
52 /*
53 * See strtoq for comments as to the logic used.
54 */
55 s = nptr;
56 do {
57 c = (unsigned char) *s++;
58 } while (isspace(c));
59 if (c == '-') {
60 neg = 1;
61 c = *s++;
62 } else {
63 neg = 0;
64 if (c == '+')
65 c = *s++;
66 }
67 if ((base == 0 || base == 16) &&
68 c == '0' && (*s == 'x' || *s == 'X')) {
69 c = s[1];
70 s += 2;
71 base = 16;
72 }
73 if (base == 0)
74 base = c == '0' ? 8 : 10;
75
76 cutoff = ULLONG_MAX / (unsigned long long)base;
77 cutlim = ULLONG_MAX % (unsigned long long)base;
78 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
79 if (isdigit(c))
80 c -= '0';
81 else if (isalpha(c))
82 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
83 else
84 break;
85 if (c >= base)
86 break;
87 if (any < 0)
88 continue;
89 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
90 any = -1;
91 acc = ULLONG_MAX;
92 errno = ERANGE;
93 } else {
94 any = 1;
95 acc *= (unsigned long long)base;
96 acc += c;
97 }
98 }
99 if (neg && any > 0)
100 acc = -acc;
101 if (endptr != 0)
102 *endptr = (char *) (any ? s - 1 : nptr);
103 return (acc);
104}
105
106__strong_alias(strtouq, strtoull);
diff --git a/src/lib/libc/stdlib/strtoumax.c b/src/lib/libc/stdlib/strtoumax.c
new file mode 100644
index 0000000000..ce6e2c00f1
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoumax.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: strtoumax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35
36/*
37 * Convert a string to a uintmax_t.
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42uintmax_t
43strtoumax(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 uintmax_t acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * See strtoq for comments as to the logic used.
52 */
53 s = nptr;
54 do {
55 c = (unsigned char) *s++;
56 } while (isspace(c));
57 if (c == '-') {
58 neg = 1;
59 c = *s++;
60 } else {
61 neg = 0;
62 if (c == '+')
63 c = *s++;
64 }
65 if ((base == 0 || base == 16) &&
66 c == '0' && (*s == 'x' || *s == 'X')) {
67 c = s[1];
68 s += 2;
69 base = 16;
70 }
71 if (base == 0)
72 base = c == '0' ? 8 : 10;
73
74 cutoff = UINTMAX_MAX / (uintmax_t)base;
75 cutlim = UINTMAX_MAX % (uintmax_t)base;
76 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
77 if (isdigit(c))
78 c -= '0';
79 else if (isalpha(c))
80 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
81 else
82 break;
83 if (c >= base)
84 break;
85 if (any < 0)
86 continue;
87 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
88 any = -1;
89 acc = UINTMAX_MAX;
90 errno = ERANGE;
91 } else {
92 any = 1;
93 acc *= (uintmax_t)base;
94 acc += c;
95 }
96 }
97 if (neg && any > 0)
98 acc = -acc;
99 if (endptr != 0)
100 *endptr = (char *) (any ? s - 1 : nptr);
101 return (acc);
102}
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
new file mode 100644
index 0000000000..878bb0a9d2
--- /dev/null
+++ b/src/lib/libc/stdlib/system.3
@@ -0,0 +1,109 @@
1.\" Copyright (c) 1990, 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. 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.\" $OpenBSD: system.3,v 1.13 2013/07/18 10:14:50 schwarze Exp $
33.\"
34.Dd $Mdocdate: July 18 2013 $
35.Dt SYSTEM 3
36.Os
37.Sh NAME
38.Nm system
39.Nd pass a command to the shell
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft int
43.Fn system "const char *string"
44.Sh DESCRIPTION
45The
46.Fn system
47function hands the argument
48.Fa string
49to the command interpreter
50.Xr sh 1 .
51The calling process waits for the shell to finish executing the command,
52ignoring
53.Dv SIGINT
54and
55.Dv SIGQUIT ,
56and blocking
57.Dv SIGCHLD .
58.Pp
59If
60.Fa string
61is
62.Dv NULL ,
63.Fn system
64will return non-zero.
65Otherwise,
66.Fn system
67returns the termination status of the shell in the format specified by
68.Xr waitpid 2 .
69.Pp
70Note that fork handlers established using
71.Xr pthread_atfork 3
72are not called when a multithreaded program calls
73.Fn system .
74.Sh RETURN VALUES
75If a child process cannot be created, or the termination status of
76the shell cannot be obtained,
77.Fn system
78returns \-1 and sets
79.Va errno
80to indicate the error.
81If execution of the shell fails,
82.Fn system
83returns the termination status for a program that terminates with a call of
84.Fn exit 127 .
85.Sh SEE ALSO
86.Xr sh 1 ,
87.Xr execve 2 ,
88.Xr waitpid 2 ,
89.Xr popen 3
90.Sh STANDARDS
91The
92.Fn system
93function conforms to
94.St -ansiC
95and
96.St -p1003.2-92 .
97.Sh HISTORY
98The
99.Fn system
100function first appeared in
101.At v6 .
102.Sh CAVEATS
103Never supply the
104.Fn system
105function with a command containing any part of an unsanitized user-supplied
106string.
107Shell meta-characters present will be honored by the
108.Xr sh 1
109command interpreter.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
new file mode 100644
index 0000000000..14ddcae8d3
--- /dev/null
+++ b/src/lib/libc/stdlib/system.c
@@ -0,0 +1,74 @@
1/* $OpenBSD: system.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1988 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/wait.h>
33#include <signal.h>
34#include <stdlib.h>
35#include <unistd.h>
36#include <paths.h>
37
38extern char **environ;
39
40int
41system(const char *command)
42{
43 pid_t pid;
44 sig_t intsave, quitsave;
45 sigset_t mask, omask;
46 int pstat;
47 char *argp[] = {"sh", "-c", NULL, NULL};
48
49 if (!command) /* just checking... */
50 return(1);
51
52 argp[2] = (char *)command;
53
54 sigemptyset(&mask);
55 sigaddset(&mask, SIGCHLD);
56 sigprocmask(SIG_BLOCK, &mask, &omask);
57 switch (pid = vfork()) {
58 case -1: /* error */
59 sigprocmask(SIG_SETMASK, &omask, NULL);
60 return(-1);
61 case 0: /* child */
62 sigprocmask(SIG_SETMASK, &omask, NULL);
63 execve(_PATH_BSHELL, argp, environ);
64 _exit(127);
65 }
66
67 intsave = signal(SIGINT, SIG_IGN);
68 quitsave = signal(SIGQUIT, SIG_IGN);
69 pid = waitpid(pid, (int *)&pstat, 0);
70 sigprocmask(SIG_SETMASK, &omask, NULL);
71 (void)signal(SIGINT, intsave);
72 (void)signal(SIGQUIT, quitsave);
73 return (pid == -1 ? -1 : pstat);
74}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..0d1d5196d8
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/* $OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14#include <search.h>
15
16typedef struct node_t
17{
18 char *key;
19 struct node_t *llink, *rlink;
20} node;
21
22/* find a node, or return 0 */
23void *
24tfind(const void *vkey, void * const *vrootp,
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..46d0bba10c
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,130 @@
1.\" $OpenBSD: tsearch.3,v 1.19 2013/06/05 03:39:23 tedu Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: June 5 2013 $
18.Dt TSEARCH 3
19.Os
20.Sh NAME
21.Nm tsearch ,
22.Nm tfind ,
23.Nm tdelete ,
24.Nm twalk
25.Nd manipulate binary search trees
26.Sh SYNOPSIS
27.In search.h
28.Ft void *
29.Fn tdelete "const void *key" "void **rootp" "int (*compar)(const void *, const void *)"
30.Ft void *
31.Fn tfind "const void *key" "void * const *rootp" "int (*compar)(const void *, const void *)"
32.Ft void *
33.Fn tsearch "const void *key" "void **rootp" "int (*compar)(const void *, const void *)"
34.Ft void
35.Fn twalk "const void *root" "void (*action)(const void *, VISIT, int)"
36.Sh DESCRIPTION
37The
38.Fn tdelete ,
39.Fn tfind ,
40.Fn tsearch ,
41and
42.Fn twalk
43functions manage binary search trees based on algorithms T and D
44from Knuth (6.2.2).
45The comparison function passed in by
46the user has the same style of return values as
47.Xr strcmp 3 .
48.Pp
49.Fn tfind
50searches for the datum matched by the argument
51.Fa key
52in the binary tree rooted at
53.Fa rootp ,
54returning a pointer to the datum if it is found and
55.Dv NULL
56if it is not.
57.Pp
58.Fn tsearch
59is identical to
60.Fn tfind
61except that if no match is found,
62.Fa key
63is inserted into the tree and a pointer to it is returned.
64If
65.Fa rootp
66points to a null value a new binary search tree is created.
67.Pp
68.Fn tdelete
69deletes a node from the specified binary search tree and returns
70a pointer to the parent of the node to be deleted.
71If the node to be deleted is the root of the binary search tree,
72.Fa rootp
73will be adjusted and an unspecified non-null pointer will be returned.
74It takes the same arguments as
75.Fn tfind
76and
77.Fn tsearch .
78.Pp
79.Fn twalk
80walks the binary search tree rooted in
81.Fa root
82and calls the function
83.Fa action
84on each node.
85.Fa action
86is called with three arguments: a pointer to the current node,
87a value from the enum
88.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
89specifying the traversal type, and a node level (where level
90zero is the root of the tree).
91.Sh RETURN VALUES
92The
93.Fn tsearch
94function returns
95.Dv NULL
96if allocation of a new node fails (usually
97due to a lack of free memory).
98.Pp
99.Fn tdelete
100returns a pointer to the parent of the deleted node or an unspecified
101non-null pointer if the root node is deleted.
102.Pp
103.Fn tfind ,
104.Fn tsearch ,
105and
106.Fn tdelete
107return
108.Dv NULL
109if
110.Fa rootp
111is
112.Dv NULL
113or the datum cannot be found.
114.Pp
115The
116.Fn twalk
117function returns no value.
118.Sh SEE ALSO
119.Xr bsearch 3 ,
120.Xr lsearch 3
121.Sh STANDARDS
122These functions conform to
123.St -p1003.1-2008 .
124.Sh CAVEATS
125The value returned when deleting the root node was unspecified before
126the
127.St -p1003.1-2008
128standard, so users of the
129.Fn tdelete
130function should be wary of relying on a specific behaviour.
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..a141085d2b
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
1/* $OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14
15#include <search.h>
16#include <stdlib.h>
17
18typedef struct node_t {
19 char *key;
20 struct node_t *left, *right;
21} node;
22
23/* find or insert datum into search tree */
24void *
25tsearch(const void *vkey, void **vrootp,
26 int (*compar)(const void *, const void *))
27{
28 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(const void *vkey, void **vrootp,
55 int (*compar)(const void *, const void *))
56{
57 node **rootp = (node **)vrootp;
58 char *key = (char *)vkey;
59 node *p = (node *)1;
60 node *q;
61 node *r;
62 int cmp;
63
64 if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
65 return ((struct node_t *)0);
66 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
67 p = *rootp;
68 rootp = (cmp < 0) ?
69 &(*rootp)->left : /* follow left branch */
70 &(*rootp)->right; /* follow right branch */
71 if (*rootp == (struct node_t *)0)
72 return ((void *)0); /* key not found */
73 }
74 r = (*rootp)->right; /* D1: */
75 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
76 q = r;
77 else if (r != (struct node_t *)0) { /* Right link is null? */
78 if (r->left == (struct node_t *)0) { /* D2: Find successor */
79 r->left = q;
80 q = r;
81 } else { /* D3: Find (struct node_t *)0 link */
82 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
83 r = q;
84 r->left = q->right;
85 q->left = (*rootp)->left;
86 q->right = (*rootp)->right;
87 }
88 }
89 free((struct node_t *) *rootp); /* D4: Free node */
90 *rootp = q; /* link parent to new node */
91 return(p);
92}
93
94/* Walk the nodes of a tree */
95static void
96trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
97{
98 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
99 (*action)(root, leaf, level);
100 else {
101 (*action)(root, preorder, level);
102 if (root->left != (struct node_t *)0)
103 trecurse(root->left, action, level + 1);
104 (*action)(root, postorder, level);
105 if (root->right != (struct node_t *)0)
106 trecurse(root->right, action, level + 1);
107 (*action)(root, endorder, level);
108 }
109}
110
111/* Walk the nodes of a tree */
112void
113twalk(const void *vroot, void (*action)(const void *, VISIT, int))
114{
115 node *root = (node *)vroot;
116
117 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
118 trecurse(root, action, 0);
119}