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.inc33
-rw-r--r--src/lib/libc/stdlib/_Exit.c22
-rw-r--r--src/lib/libc/stdlib/__mktemp4.c83
-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.377
-rw-r--r--src/lib/libc/stdlib/abort.c64
-rw-r--r--src/lib/libc/stdlib/abs.375
-rw-r--r--src/lib/libc/stdlib/abs.c38
-rw-r--r--src/lib/libc/stdlib/alloca.374
-rw-r--r--src/lib/libc/stdlib/atexit.397
-rw-r--r--src/lib/libc/stdlib/atexit.c256
-rw-r--r--src/lib/libc/stdlib/atexit.h61
-rw-r--r--src/lib/libc/stdlib/atof.381
-rw-r--r--src/lib/libc/stdlib/atof.c37
-rw-r--r--src/lib/libc/stdlib/atoi.389
-rw-r--r--src/lib/libc/stdlib/atoi.c38
-rw-r--r--src/lib/libc/stdlib/atol.368
-rw-r--r--src/lib/libc/stdlib/atol.c37
-rw-r--r--src/lib/libc/stdlib/atoll.368
-rw-r--r--src/lib/libc/stdlib/atoll.c37
-rw-r--r--src/lib/libc/stdlib/bsearch.384
-rw-r--r--src/lib/libc/stdlib/bsearch.c69
-rw-r--r--src/lib/libc/stdlib/div.363
-rw-r--r--src/lib/libc/stdlib/div.c72
-rw-r--r--src/lib/libc/stdlib/drand48.c30
-rw-r--r--src/lib/libc/stdlib/ecvt.3166
-rw-r--r--src/lib/libc/stdlib/ecvt.c104
-rw-r--r--src/lib/libc/stdlib/erand48.c26
-rw-r--r--src/lib/libc/stdlib/exit.3102
-rw-r--r--src/lib/libc/stdlib/exit.c57
-rw-r--r--src/lib/libc/stdlib/gcvt.c123
-rw-r--r--src/lib/libc/stdlib/getenv.3191
-rw-r--r--src/lib/libc/stdlib/getenv.c78
-rw-r--r--src/lib/libc/stdlib/getopt.3365
-rw-r--r--src/lib/libc/stdlib/getopt_long.3460
-rw-r--r--src/lib/libc/stdlib/getopt_long.c513
-rw-r--r--src/lib/libc/stdlib/getsubopt.3162
-rw-r--r--src/lib/libc/stdlib/getsubopt.c92
-rw-r--r--src/lib/libc/stdlib/hcreate.3234
-rw-r--r--src/lib/libc/stdlib/hcreate.c189
-rw-r--r--src/lib/libc/stdlib/heapsort.c175
-rw-r--r--src/lib/libc/stdlib/icdb.c391
-rw-r--r--src/lib/libc/stdlib/icdb_new.368
-rw-r--r--src/lib/libc/stdlib/imaxabs.370
-rw-r--r--src/lib/libc/stdlib/imaxabs.c38
-rw-r--r--src/lib/libc/stdlib/imaxdiv.365
-rw-r--r--src/lib/libc/stdlib/imaxdiv.c50
-rw-r--r--src/lib/libc/stdlib/insque.3103
-rw-r--r--src/lib/libc/stdlib/insque.c54
-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.388
-rw-r--r--src/lib/libc/stdlib/labs.c37
-rw-r--r--src/lib/libc/stdlib/lcong48.c36
-rw-r--r--src/lib/libc/stdlib/ldiv.371
-rw-r--r--src/lib/libc/stdlib/ldiv.c50
-rw-r--r--src/lib/libc/stdlib/llabs.c40
-rw-r--r--src/lib/libc/stdlib/lldiv.373
-rw-r--r--src/lib/libc/stdlib/lldiv.c52
-rw-r--r--src/lib/libc/stdlib/lrand48.c24
-rw-r--r--src/lib/libc/stdlib/lsearch.3106
-rw-r--r--src/lib/libc/stdlib/lsearch.c70
-rw-r--r--src/lib/libc/stdlib/malloc.3860
-rw-r--r--src/lib/libc/stdlib/malloc.c2781
-rw-r--r--src/lib/libc/stdlib/merge.c336
-rw-r--r--src/lib/libc/stdlib/mkdtemp.c41
-rw-r--r--src/lib/libc/stdlib/mkstemp.c64
-rw-r--r--src/lib/libc/stdlib/mktemp.3431
-rw-r--r--src/lib/libc/stdlib/mktemp.c48
-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.397
-rw-r--r--src/lib/libc/stdlib/posix_openpt.3102
-rw-r--r--src/lib/libc/stdlib/posix_pty.c120
-rw-r--r--src/lib/libc/stdlib/ptsname.3160
-rw-r--r--src/lib/libc/stdlib/qsort.3276
-rw-r--r--src/lib/libc/stdlib/qsort.c238
-rw-r--r--src/lib/libc/stdlib/radixsort.3151
-rw-r--r--src/lib/libc/stdlib/radixsort.c294
-rw-r--r--src/lib/libc/stdlib/rand.3135
-rw-r--r--src/lib/libc/stdlib/rand.c74
-rw-r--r--src/lib/libc/stdlib/rand48.3240
-rw-r--r--src/lib/libc/stdlib/rand48.h38
-rw-r--r--src/lib/libc/stdlib/random.3197
-rw-r--r--src/lib/libc/stdlib/random.c419
-rw-r--r--src/lib/libc/stdlib/reallocarray.c39
-rw-r--r--src/lib/libc/stdlib/realpath.3165
-rw-r--r--src/lib/libc/stdlib/realpath.c42
-rw-r--r--src/lib/libc/stdlib/recallocarray.c81
-rw-r--r--src/lib/libc/stdlib/remque.c48
-rw-r--r--src/lib/libc/stdlib/seed48.c45
-rw-r--r--src/lib/libc/stdlib/setenv.c185
-rw-r--r--src/lib/libc/stdlib/srand48.c38
-rw-r--r--src/lib/libc/stdlib/strtod.3176
-rw-r--r--src/lib/libc/stdlib/strtoimax.c151
-rw-r--r--src/lib/libc/stdlib/strtol.3273
-rw-r--r--src/lib/libc/stdlib/strtol.c151
-rw-r--r--src/lib/libc/stdlib/strtoll.c156
-rw-r--r--src/lib/libc/stdlib/strtonum.3152
-rw-r--r--src/lib/libc/stdlib/strtonum.c66
-rw-r--r--src/lib/libc/stdlib/strtoul.3260
-rw-r--r--src/lib/libc/stdlib/strtoul.c110
-rw-r--r--src/lib/libc/stdlib/strtoull.c114
-rw-r--r--src/lib/libc/stdlib/strtoumax.c109
-rw-r--r--src/lib/libc/stdlib/system.3116
-rw-r--r--src/lib/libc/stdlib/system.c89
-rw-r--r--src/lib/libc/stdlib/tfind.c40
-rw-r--r--src/lib/libc/stdlib/thread_atexit.c44
-rw-r--r--src/lib/libc/stdlib/tsearch.3126
-rw-r--r--src/lib/libc/stdlib/tsearch.c118
112 files changed, 0 insertions, 16504 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
deleted file mode 100644
index f5e9a9fe4e..0000000000
--- a/src/lib/libc/stdlib/Makefile.inc
+++ /dev/null
@@ -1,33 +0,0 @@
1# $OpenBSD: Makefile.inc,v 1.66 2024/01/19 19:45:02 millert 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 exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c insque.c \
9 l64a.c llabs.c lldiv.c lsearch.c malloc.c __mktemp4.c mkdtemp.c \
10 mkstemp.c mktemp.c reallocarray.c merge.c posix_pty.c qsort.c \
11 radixsort.c rand.c random.c realpath.c remque.c setenv.c strtoimax.c \
12 strtol.c strtoll.c strtonum.c strtoul.c strtoull.c strtoumax.c \
13 system.c \
14 tfind.c thread_atexit.c tsearch.c \
15 _rand48.c drand48.c erand48.c jrand48.c \
16 lcong48.c lrand48.c mrand48.c nrand48.c seed48.c srand48.c \
17 _Exit.c icdb.c
18
19.if (${MACHINE_CPU} == "i386")
20SRCS+= abs.S div.S labs.S ldiv.S
21.elif (${MACHINE_CPU} == "alpha")
22# XXX should be .S's
23SRCS+= abs.c div.c labs.c ldiv.c
24.else
25SRCS+= abs.c div.c labs.c ldiv.c
26.endif
27
28MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
29 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
30 getsubopt.3 hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 \
31 lldiv.3 lsearch.3 malloc.3 mktemp.3 posix_memalign.3 posix_openpt.3 \
32 ptsname.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
33 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3
diff --git a/src/lib/libc/stdlib/_Exit.c b/src/lib/libc/stdlib/_Exit.c
deleted file mode 100644
index ccf64c2e87..0000000000
--- a/src/lib/libc/stdlib/_Exit.c
+++ /dev/null
@@ -1,22 +0,0 @@
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/__mktemp4.c b/src/lib/libc/stdlib/__mktemp4.c
deleted file mode 100644
index 4b4500018b..0000000000
--- a/src/lib/libc/stdlib/__mktemp4.c
+++ /dev/null
@@ -1,83 +0,0 @@
1/* $OpenBSD: __mktemp4.c,v 1.1 2024/01/19 19:45:02 millert Exp $ */
2/*
3 * Copyright (c) 1996-1998, 2008 Theo de Raadt
4 * Copyright (c) 1997, 2008-2009, 2024 Todd C. Miller
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 <errno.h>
20#include <limits.h>
21#include <stdlib.h>
22#include <string.h>
23
24#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
25#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
26#define MIN_X 6
27
28#ifndef nitems
29#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
30#endif
31
32/*
33 * Internal driver for the mktemp(3) family of functions.
34 * The supplied callback does the actual work of testing or
35 * creating the file/directory.
36 */
37int
38__mktemp4(char *path, int slen, int flags, int (*cb)(const char *, int))
39{
40 char *start, *cp, *ep;
41 const char tempchars[] = TEMPCHARS;
42 unsigned int tries;
43 size_t len;
44 int ret;
45
46 len = strlen(path);
47 if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) {
48 errno = EINVAL;
49 return -1;
50 }
51 ep = path + len - slen;
52
53 for (start = ep; start > path && start[-1] == 'X'; start--)
54 ;
55 if (ep - start < MIN_X) {
56 errno = EINVAL;
57 return -1;
58 }
59
60 tries = INT_MAX;
61 do {
62 cp = start;
63 do {
64 unsigned short rbuf[16];
65 unsigned int i;
66
67 /*
68 * Avoid lots of arc4random() calls by using
69 * a buffer sized for up to 16 Xs at a time.
70 */
71 arc4random_buf(rbuf, sizeof(rbuf));
72 for (i = 0; i < nitems(rbuf) && cp != ep; i++)
73 *cp++ = tempchars[rbuf[i] % NUM_CHARS];
74 } while (cp != ep);
75
76 ret = cb(path, flags);
77 if (ret != -1 || errno != EEXIST)
78 return ret;
79 } while (--tries);
80
81 errno = EEXIST;
82 return -1;
83}
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
deleted file mode 100644
index 7c950f7cee..0000000000
--- a/src/lib/libc/stdlib/_rand48.c
+++ /dev/null
@@ -1,47 +0,0 @@
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
deleted file mode 100644
index c34af99c88..0000000000
--- a/src/lib/libc/stdlib/a64l.3
+++ /dev/null
@@ -1,133 +0,0 @@
1.\" $OpenBSD: a64l.3,v 1.13 2019/01/25 00:19:25 millert Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
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: January 25 2019 $
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
deleted file mode 100644
index 5312929c6f..0000000000
--- a/src/lib/libc/stdlib/a64l.c
+++ /dev/null
@@ -1,42 +0,0 @@
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
deleted file mode 100644
index 2f15cd827c..0000000000
--- a/src/lib/libc/stdlib/abort.3
+++ /dev/null
@@ -1,77 +0,0 @@
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.11 2014/05/14 21:54:20 tedu Exp $
33.\"
34.Dd $Mdocdate: May 14 2014 $
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
51Some implementations may flush output streams before terminating.
52This implementation does not.
53.Sh RETURN VALUES
54The
55.Fn abort
56function never returns.
57.Sh SEE ALSO
58.Xr sigaction 2 ,
59.Xr exit 3
60.Sh STANDARDS
61The
62.Fn abort
63function conforms to
64.St -p1003.1-90 .
65.Sh HISTORY
66The
67.Fn abort
68function first appeared in
69.At v5 .
70.Pp
71Historically, previous standards required
72.Fn abort
73to flush and close output streams, but this conflicted with the requirement
74that
75.Fn abort
76be async signal safe.
77As a result, the flushing requirement was dropped.
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
deleted file mode 100644
index 6c22ecd2b0..0000000000
--- a/src/lib/libc/stdlib/abort.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/* $OpenBSD: abort.c,v 1.21 2017/08/12 22:59:52 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 <string.h>
34#include <unistd.h>
35
36
37void
38abort(void)
39{
40 sigset_t mask;
41 struct sigaction sa;
42
43 sigfillset(&mask);
44 /*
45 * don't block SIGABRT to give any handler a chance; we ignore
46 * any errors -- X311J doesn't allow abort to return anyway.
47 */
48 sigdelset(&mask, SIGABRT);
49 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
50
51 (void)raise(SIGABRT);
52
53 /*
54 * if SIGABRT ignored, or caught and the handler returns, do
55 * it again, only harder.
56 */
57 memset(&sa, 0, sizeof(sa));
58 sa.sa_handler = SIG_DFL;
59 (void)sigaction(SIGABRT, &sa, NULL);
60 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
61 (void)raise(SIGABRT);
62 _exit(1);
63}
64DEF_STRONG(abort);
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
deleted file mode 100644
index afacc985df..0000000000
--- a/src/lib/libc/stdlib/abs.3
+++ /dev/null
@@ -1,75 +0,0 @@
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.12 2019/01/18 07:32:17 schwarze Exp $
33.\"
34.Dd $Mdocdate: January 18 2019 $
35.Dt ABS 3
36.Os
37.Sh NAME
38.Nm abs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.In limits.h
42.In stdlib.h
43.Ft int
44.Fn abs "int j"
45.Sh DESCRIPTION
46The
47.Fn abs
48function computes the absolute value of the integer
49.Fa j .
50.Sh RETURN VALUES
51The
52.Fn abs
53function returns the absolute value.
54.Sh SEE ALSO
55.Xr cabs 3 ,
56.Xr floor 3 ,
57.Xr hypot 3 ,
58.Xr imaxabs 3 ,
59.Xr labs 3
60.Sh STANDARDS
61The
62.Fn abs
63function conforms to
64.St -ansiC .
65.Sh HISTORY
66The
67.Fn abs
68function first appeared in
69.At v6 .
70.Sh CAVEATS
71The result of applying
72.Fn abs
73to
74.Dv INT_MIN
75is undefined.
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
deleted file mode 100644
index 0e39cc5536..0000000000
--- a/src/lib/libc/stdlib/abs.c
+++ /dev/null
@@ -1,38 +0,0 @@
1/* $OpenBSD: abs.c,v 1.6 2015/09/13 08:31:47 guenther 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}
38DEF_STRONG(abs);
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
deleted file mode 100644
index 5252ba586f..0000000000
--- a/src/lib/libc/stdlib/alloca.3
+++ /dev/null
@@ -1,74 +0,0 @@
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.14 2015/01/17 18:01:43 tedu Exp $
29.\"
30.Dd $Mdocdate: January 17 2015 $
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 malloc 3
55.\" .Sh HISTORY
56.\" The
57.\" .Fn alloca
58.\" function appeared in
59.\" .Bx ?? .
60.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
61.\" The first man page (or link to a man page that I can find at the
62.\" moment is 4.3...
63.Sh CAVEATS
64The
65.Fn alloca
66function is unsafe because it cannot ensure that the pointer
67returned points to a valid and usable block of memory.
68The allocation made may exceed the bounds of the stack, or even go
69further into other objects in memory, and
70.Fn alloca
71cannot determine such an error.
72Avoid
73.Fn alloca
74with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
deleted file mode 100644
index 3a7e0d978a..0000000000
--- a/src/lib/libc/stdlib/atexit.3
+++ /dev/null
@@ -1,97 +0,0 @@
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.13 2022/02/06 00:29:02 jsg Exp $
33.\"
34.Dd $Mdocdate: February 6 2022 $
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
58If a shared object is unloaded from process memory using
59.Xr dlclose 3 ,
60then any functions registered by calling
61.Fn atexit
62from that shared object will be called in reverse order and unregistered.
63Note that it is the source of the call to
64.Fn atexit
65that matters, not the source of the function that was registered.
66.Pp
67.Fn atexit
68is very difficult to use correctly without creating
69.Xr exit 3 Ns -time
70races.
71Unless absolutely necessary, avoid using it.
72.Sh RETURN VALUES
73The
74.Nm
75function returns the value 0 if successful; otherwise a non-zero
76value is returned and the global variable
77.Va errno
78is set to indicate the error.
79.Sh ERRORS
80.Bl -tag -width Er
81.It Bq Er ENOMEM
82No memory was available to add the function to the list.
83The existing list of functions is unmodified.
84.El
85.Sh SEE ALSO
86.Xr dlclose 3 ,
87.Xr exit 3
88.Sh STANDARDS
89The
90.Fn atexit
91function conforms to
92.St -ansiC .
93.Pp
94Setting
95.Va errno
96on error and the behavior when a shared object is unloaded
97are extensions to that standard.
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
deleted file mode 100644
index 3334617b65..0000000000
--- a/src/lib/libc/stdlib/atexit.c
+++ /dev/null
@@ -1,256 +0,0 @@
1/* $OpenBSD: atexit.c,v 1.29 2022/12/27 17:10:06 jmc 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 <tib.h>
37#include <unistd.h>
38
39#include "atexit.h"
40#include "atfork.h"
41#include "thread_private.h"
42
43struct atexit *__atexit;
44static int restartloop;
45
46/* define and initialize the list */
47struct atfork_listhead _atfork_list = TAILQ_HEAD_INITIALIZER(_atfork_list);
48
49
50/*
51 * Function pointers are stored in a linked list of pages. The list
52 * is initially empty, and pages are allocated on demand. The first
53 * function pointer in the first allocated page (the last one in
54 * the linked list) is reserved for the cleanup function.
55 *
56 * Outside the following functions, all pages are mprotect()'ed
57 * to prevent unintentional/malicious corruption.
58 */
59
60/*
61 * Register a function to be performed at exit or when a shared object
62 * with the given dso handle is unloaded dynamically. Also used as
63 * the backend for atexit(). For more info on this API, see:
64 *
65 * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
66 */
67int
68__cxa_atexit(void (*func)(void *), void *arg, void *dso)
69{
70 struct atexit *p;
71 struct atexit_fn *fnp;
72 int pgsize = getpagesize();
73 int ret = -1;
74
75 if (pgsize < sizeof(*p))
76 return (-1);
77 _ATEXIT_LOCK();
78 p = __atexit;
79 if (p != NULL) {
80 if (p->ind + 1 >= p->max)
81 p = NULL;
82 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
83 goto unlock;
84 }
85 if (p == NULL) {
86 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
87 MAP_ANON | MAP_PRIVATE, -1, 0);
88 if (p == MAP_FAILED)
89 goto unlock;
90 if (__atexit == NULL) {
91 memset(&p->fns[0], 0, sizeof(p->fns[0]));
92 p->ind = 1;
93 } else
94 p->ind = 0;
95 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
96 sizeof(p->fns[0]);
97 p->next = __atexit;
98 __atexit = p;
99 }
100 fnp = &p->fns[p->ind++];
101 fnp->fn_ptr = func;
102 fnp->fn_arg = arg;
103 fnp->fn_dso = dso;
104 if (mprotect(p, pgsize, PROT_READ))
105 goto unlock;
106 restartloop = 1;
107 ret = 0;
108unlock:
109 _ATEXIT_UNLOCK();
110 return (ret);
111}
112DEF_STRONG(__cxa_atexit);
113
114/*
115 * Copy of atexit() used by libc and anything statically linked into the
116 * executable. This passes NULL for the dso, so the callbacks are only
117 * invoked by exit() and not dlclose()
118 */
119int
120atexit(void (*fn)(void))
121{
122 return (__cxa_atexit((void (*)(void *))fn, NULL, NULL));
123}
124DEF_STRONG(atexit);
125
126void
127_thread_finalize(void)
128{
129 struct tib *tib = TIB_GET();
130
131 while (tib->tib_atexit) {
132 struct thread_atexit_fn *fnp = tib->tib_atexit;
133 tib->tib_atexit = fnp->next;
134 fnp->func(fnp->arg);
135 free(fnp);
136 }
137}
138
139/*
140 * Call all handlers registered with __cxa_atexit() for the shared
141 * object owning 'dso'.
142 * Note: if 'dso' is NULL, then all remaining handlers are called.
143 */
144void
145__cxa_finalize(void *dso)
146{
147 struct atexit *p, *q;
148 struct atexit_fn fn;
149 int n, pgsize = getpagesize();
150 static int call_depth;
151
152 if (dso == NULL)
153 _thread_finalize();
154
155 _ATEXIT_LOCK();
156 call_depth++;
157
158restart:
159 restartloop = 0;
160 for (p = __atexit; p != NULL; p = p->next) {
161 for (n = p->ind; --n >= 0;) {
162 if (p->fns[n].fn_ptr == NULL)
163 continue; /* already called */
164 if (dso != NULL && dso != p->fns[n].fn_dso)
165 continue; /* wrong DSO */
166
167 /*
168 * Mark handler as having been already called to avoid
169 * dupes and loops, then call the appropriate function.
170 */
171 fn = p->fns[n];
172 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
173 p->fns[n].fn_ptr = NULL;
174 mprotect(p, pgsize, PROT_READ);
175 }
176 _ATEXIT_UNLOCK();
177 (*fn.fn_ptr)(fn.fn_arg);
178 _ATEXIT_LOCK();
179 if (restartloop)
180 goto restart;
181 }
182 }
183
184 call_depth--;
185
186 /*
187 * If called via exit(), unmap the pages since we have now run
188 * all the handlers. We defer this until calldepth == 0 so that
189 * we don't unmap things prematurely if called recursively.
190 */
191 if (dso == NULL && call_depth == 0) {
192 for (p = __atexit; p != NULL; ) {
193 q = p;
194 p = p->next;
195 munmap(q, pgsize);
196 }
197 __atexit = NULL;
198 }
199 _ATEXIT_UNLOCK();
200
201 /*
202 * If unloading a DSO, unregister any atfork handlers registered
203 * by it. Skip the locking if the list is currently empty.
204 */
205 if (dso != NULL && TAILQ_FIRST(&_atfork_list) != NULL) {
206 struct atfork_fn *af, *afnext;
207
208 _ATFORK_LOCK();
209 TAILQ_FOREACH_SAFE(af, &_atfork_list, fn_next, afnext)
210 if (af->fn_dso == dso) {
211 TAILQ_REMOVE(&_atfork_list, af, fn_next);
212 free(af);
213 }
214 _ATFORK_UNLOCK();
215
216 }
217}
218DEF_STRONG(__cxa_finalize);
219
220/*
221 * Register the cleanup function
222 */
223void
224__atexit_register_cleanup(void (*func)(void))
225{
226 struct atexit *p;
227 int pgsize = getpagesize();
228
229 if (pgsize < sizeof(*p))
230 return;
231 _ATEXIT_LOCK();
232 p = __atexit;
233 while (p != NULL && p->next != NULL)
234 p = p->next;
235 if (p == NULL) {
236 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
237 MAP_ANON | MAP_PRIVATE, -1, 0);
238 if (p == MAP_FAILED)
239 goto unlock;
240 p->ind = 1;
241 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
242 sizeof(p->fns[0]);
243 p->next = NULL;
244 __atexit = p;
245 } else {
246 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
247 goto unlock;
248 }
249 p->fns[0].fn_ptr = (void (*)(void *))func;
250 p->fns[0].fn_arg = NULL;
251 p->fns[0].fn_dso = NULL;
252 mprotect(p, pgsize, PROT_READ);
253 restartloop = 1;
254unlock:
255 _ATEXIT_UNLOCK();
256}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
deleted file mode 100644
index f2fa7bd83f..0000000000
--- a/src/lib/libc/stdlib/atexit.h
+++ /dev/null
@@ -1,61 +0,0 @@
1/* $OpenBSD: atexit.h,v 1.12 2017/12/16 20:06:56 guenther 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 void (*fn_ptr)(void *);
39 void *fn_arg; /* argument for CXA callback */
40 void *fn_dso; /* shared module handle */
41 } fns[1]; /* the table itself */
42};
43
44/* a chain of these are hung off each thread's TIB's tib_atexit member */
45struct thread_atexit_fn {
46 void (*func)(void *);
47 void *arg;
48 struct thread_atexit_fn *next;
49};
50
51__BEGIN_HIDDEN_DECLS
52extern struct atexit *__atexit; /* points to head of LIFO stack */
53__END_HIDDEN_DECLS
54
55int __cxa_atexit(void (*)(void *), void *, void *);
56int __cxa_thread_atexit(void (*)(void *), void *, void *);
57void __cxa_finalize(void *);
58
59PROTO_NORMAL(__cxa_atexit);
60PROTO_STD_DEPRECATED(__cxa_thread_atexit);
61PROTO_NORMAL(__cxa_finalize);
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
deleted file mode 100644
index 7d1f09d1a4..0000000000
--- a/src/lib/libc/stdlib/atof.3
+++ /dev/null
@@ -1,81 +0,0 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. 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.10 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
35.Dt ATOF 3
36.Os
37.Sh NAME
38.Nm atof
39.Nd convert ASCII string to double
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft double
43.Fn atof "const char *nptr"
44.Sh DESCRIPTION
45The
46.Fn atof
47function converts the initial portion of the string pointed to by
48.Fa nptr
49to
50.Vt double
51representation.
52.Pp
53It is equivalent to:
54.Bd -literal -offset indent
55strtod(nptr, (char **)NULL);
56.Ed
57.Sh SEE ALSO
58.Xr atoi 3 ,
59.Xr atol 3 ,
60.Xr strtod 3 ,
61.Xr strtol 3 ,
62.Xr strtoul 3
63.Sh STANDARDS
64The
65.Fn atof
66function conforms to
67.St -ansiC .
68.Sh HISTORY
69An
70.Fn atof
71function first appeared in
72.At v1 .
73.Sh CAVEATS
74On systems other than
75.Ox ,
76the
77.Dv LC_NUMERIC
78.Xr locale 1
79category can cause parsing failures; see CAVEATS in
80.Xr setlocale 3
81for details.
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
deleted file mode 100644
index d14b58b070..0000000000
--- a/src/lib/libc/stdlib/atof.c
+++ /dev/null
@@ -1,37 +0,0 @@
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
deleted file mode 100644
index 92d8de93a6..0000000000
--- a/src/lib/libc/stdlib/atoi.3
+++ /dev/null
@@ -1,89 +0,0 @@
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.13 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
35.Dt ATOI 3
36.Os
37.Sh NAME
38.Nm atoi
39.Nd convert ASCII string to integer
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft int
43.Fn atoi "const char *nptr"
44.Sh DESCRIPTION
45The
46.Fn atoi
47function converts the initial portion of the string pointed to by
48.Fa nptr
49to
50.Vt integer
51representation.
52.Pp
53It is equivalent to:
54.Bd -literal -offset indent
55(int)strtol(nptr, (char **)NULL, 10);
56.Ed
57.Sh SEE ALSO
58.Xr atof 3 ,
59.Xr atol 3 ,
60.Xr strtod 3 ,
61.Xr strtol 3 ,
62.Xr strtonum 3 ,
63.Xr strtoul 3
64.Sh STANDARDS
65The
66.Fn atoi
67function conforms to
68.St -ansiC .
69.Sh HISTORY
70An
71.Fn atoi
72function first appeared in
73.At v1 .
74.Sh CAVEATS
75.Nm
76does no overflow checking, handles unsigned numbers poorly,
77and handles strings containing trailing extra characters
78(like
79.Dq "123abc" )
80poorly.
81Careful use of
82.Xr strtol 3
83and
84.Xr strtoul 3
85can alleviate these problems,
86but
87.Xr strtonum 3
88can be used to convert numbers from strings much more safely
89and easily.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
deleted file mode 100644
index 7c9eb1331b..0000000000
--- a/src/lib/libc/stdlib/atoi.c
+++ /dev/null
@@ -1,38 +0,0 @@
1/* $OpenBSD: atoi.c,v 1.6 2015/09/13 08:31:47 guenther 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}
38DEF_STRONG(atoi);
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
deleted file mode 100644
index f67ca7da6c..0000000000
--- a/src/lib/libc/stdlib/atol.3
+++ /dev/null
@@ -1,68 +0,0 @@
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.11 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
35.Dt ATOL 3
36.Os
37.Sh NAME
38.Nm atol
39.Nd convert ASCII string to long integer
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft long
43.Fn atol "const char *nptr"
44.Sh DESCRIPTION
45The
46.Fn atol
47function converts the initial portion of the string pointed to by
48.Fa nptr
49to
50.Vt long integer
51representation.
52.Pp
53It is equivalent to:
54.Bd -literal -offset indent
55strtol(nptr, (char **)NULL, 10);
56.Ed
57.Sh SEE ALSO
58.Xr atof 3 ,
59.Xr atoi 3 ,
60.Xr atoll 3 ,
61.Xr strtod 3 ,
62.Xr strtol 3 ,
63.Xr strtoul 3
64.Sh STANDARDS
65The
66.Fn atol
67function conforms to
68.St -isoC-99 .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
deleted file mode 100644
index 1970804401..0000000000
--- a/src/lib/libc/stdlib/atol.c
+++ /dev/null
@@ -1,37 +0,0 @@
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
deleted file mode 100644
index c2b606dda9..0000000000
--- a/src/lib/libc/stdlib/atoll.3
+++ /dev/null
@@ -1,68 +0,0 @@
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.9 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
35.Dt ATOLL 3
36.Os
37.Sh NAME
38.Nm atoll
39.Nd convert ASCII string to long long integer
40.Sh SYNOPSIS
41.In stdlib.h
42.Ft long long
43.Fn atoll "const char *nptr"
44.Sh DESCRIPTION
45The
46.Fn atoll
47function converts the initial portion of the string pointed to by
48.Fa nptr
49to
50.Vt long long integer
51representation.
52.Pp
53It is equivalent to:
54.Bd -literal -offset indent
55strtoll(nptr, (char **)NULL, 10);
56.Ed
57.Sh SEE ALSO
58.Xr atof 3 ,
59.Xr atoi 3 ,
60.Xr atol 3 ,
61.Xr strtod 3 ,
62.Xr strtol 3 ,
63.Xr strtoul 3
64.Sh STANDARDS
65The
66.Fn atoll
67function conforms to
68.St -isoC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
deleted file mode 100644
index 32caf299e4..0000000000
--- a/src/lib/libc/stdlib/atoll.c
+++ /dev/null
@@ -1,37 +0,0 @@
1/* $OpenBSD: atoll.c,v 1.4 2021/10/24 10:05:23 jsg 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(const char *str)
35{
36 return(strtoll(str, (char **)NULL, 10));
37}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
deleted file mode 100644
index 9c66eac0fe..0000000000
--- a/src/lib/libc/stdlib/bsearch.3
+++ /dev/null
@@ -1,84 +0,0 @@
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.10 2015/11/30 17:03:05 jmc Exp $
33.\"
34.Dd $Mdocdate: November 30 2015 $
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 dbopen 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
deleted file mode 100644
index 6df44d6b4f..0000000000
--- a/src/lib/libc/stdlib/bsearch.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* $OpenBSD: bsearch.c,v 1.9 2021/12/02 20:58:01 cheloha 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 <stdlib.h>
32
33/*
34 * Perform a binary search.
35 *
36 * The code below is a bit sneaky. After a comparison fails, we
37 * divide the work in half by moving either left or right. If lim
38 * is odd, moving left simply involves halving lim: e.g., when lim
39 * is 5 we look at item 2, so we change lim to 2 so that we will
40 * look at items 0 & 1. If lim is even, the same applies. If lim
41 * is odd, moving right again involves halving lim, this time moving
42 * the base up one item past p: e.g., when lim is 5 we change base
43 * to item 3 and make lim 2 so that we will look at items 3 and 4.
44 * If lim is even, however, we have to shrink it by one before
45 * halving: e.g., when lim is 4, we still looked at item 2, so we
46 * have to make lim 3, then halve, obtaining 1, so that we will only
47 * look at item 3.
48 */
49void *
50bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
51 int (*compar)(const void *, const void *))
52{
53 const char *base = base0;
54 const void *p;
55 size_t lim;
56 int cmp;
57
58 for (lim = nmemb; lim != 0; lim >>= 1) {
59 p = base + (lim >> 1) * size;
60 cmp = (*compar)(key, p);
61 if (cmp == 0)
62 return ((void *)p);
63 if (cmp > 0) { /* key > p: move right */
64 base = (char *)p + size;
65 lim--;
66 } /* else move left */
67 }
68 return (NULL);
69}
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
deleted file mode 100644
index b4b42ba8ec..0000000000
--- a/src/lib/libc/stdlib/div.3
+++ /dev/null
@@ -1,63 +0,0 @@
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.13 2022/09/11 06:38:11 jmc Exp $
31.\"
32.Dd $Mdocdate: September 11 2022 $
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.Vt 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.Sh STANDARDS
60The
61.Fn div
62function conforms to
63.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
deleted file mode 100644
index 5e6164f0bb..0000000000
--- a/src/lib/libc/stdlib/div.c
+++ /dev/null
@@ -1,72 +0,0 @@
1/* $OpenBSD: div.c,v 1.7 2022/12/27 17:10:06 jmc 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 remainder 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}
72DEF_STRONG(div);
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
deleted file mode 100644
index 429e4cf378..0000000000
--- a/src/lib/libc/stdlib/drand48.c
+++ /dev/null
@@ -1,30 +0,0 @@
1/* $OpenBSD: drand48.c,v 1.7 2015/09/14 13:30:17 guenther 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 <math.h>
16#include "rand48.h"
17
18double
19drand48(void)
20{
21 if (__rand48_deterministic == 0) {
22 unsigned short rseed[3];
23
24 arc4random_buf(rseed, sizeof rseed);
25 return ldexp((double) rseed[0], -48) +
26 ldexp((double) rseed[1], -32) +
27 ldexp((double) rseed[2], -16);
28 }
29 return erand48(__rand48_seed);
30}
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
deleted file mode 100644
index f478f8e4b0..0000000000
--- a/src/lib/libc/stdlib/ecvt.3
+++ /dev/null
@@ -1,166 +0,0 @@
1.\" $OpenBSD: ecvt.3,v 1.13 2019/01/25 00:19:25 millert Exp $
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <millert@openbsd.org>
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: January 25 2019 $
22.Dt ECVT 3
23.Os
24.Sh NAME
25.Nm ecvt ,
26.Nm fcvt ,
27.Nm gcvt
28.Nd convert double to ASCII string
29.Sh SYNOPSIS
30.In stdlib.h
31.Ft char *
32.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
33.Ft char *
34.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
35.Ft char *
36.Fn gcvt "double value" "int ndigit" "char *buf"
37.Sh DESCRIPTION
38.Bf -symbolic
39These functions are provided for compatibility with legacy code.
40New code should use the
41.Xr snprintf 3
42function for improved safety and portability.
43.Ef
44.Pp
45The
46.Fn ecvt ,
47.Fn fcvt
48and
49.Fn gcvt
50functions convert the double precision floating-point number
51.Fa value
52to a NUL-terminated
53.Tn ASCII
54string.
55.Pp
56The
57.Fn ecvt
58function converts
59.Fa value
60to a NUL-terminated string of exactly
61.Fa ndigit
62digits and returns a pointer to that string.
63The result is padded with zeroes from left to right as needed.
64There are no leading zeroes unless
65.Fa value
66itself is 0.
67The least significant digit is rounded in an implementation-dependent manner.
68The position of the decimal point relative to the beginning of the string
69is stored in
70.Fa decpt .
71A negative value indicates that the decimal point is located
72to the left of the returned digits (this occurs when there is no
73whole number component to
74.Fa value ) .
75If
76.Fa value
77is zero, it is unspecified whether the integer pointed to by
78.Fa decpt
79will be 0 or 1.
80The decimal point itself is not included in the returned string.
81If the sign of the result is negative, the integer pointed to by
82.Fa sign
83is non-zero; otherwise, it is 0.
84.Pp
85If the converted value is out of range or is not representable,
86the contents of the returned string are unspecified.
87.Pp
88The
89.Fn fcvt
90function is identical to
91.Fn ecvt
92with the exception that
93.Fa ndigit
94specifies the number of digits after the decimal point (zero-padded as
95needed).
96.Pp
97The
98.Fn gcvt
99function converts
100.Fa value
101to a NUL-terminated string similar to the %g
102.Xr printf 3
103format specifier and stores the result in
104.Fa buf .
105It produces
106.Fa ndigit
107significant digits similar to the %f
108.Xr printf 3
109format specifier where possible.
110If
111.Fa ndigit
112does allow sufficient precision, the result is stored in
113exponential notation similar to the %e
114.Xr printf 3
115format specifier.
116If
117.Fa value
118is less than zero,
119.Fa buf
120will be prefixed with a minus sign.
121A decimal point is included in the returned string if
122.Fa value
123is not a whole number.
124Unlike the
125.Fn ecvt
126and
127.Fn fcvt
128functions,
129.Fa buf
130is not zero-padded.
131.Sh RETURN VALUES
132The
133.Fn ecvt ,
134.Fn fcvt
135and
136.Fn gcvt
137functions return a NUL-terminated string representation of
138.Fa value .
139.Sh SEE ALSO
140.Xr printf 3 ,
141.Xr strtod 3
142.Sh STANDARDS
143The
144.Fn ecvt ,
145.Fn fcvt
146and
147.Fn gcvt
148functions conform to
149.St -p1003.1-2001 ;
150as of
151.St -p1003.1-2008
152they are no longer a part of the standard.
153.Sh CAVEATS
154The
155.Fn ecvt
156and
157.Fn fcvt
158functions return a pointer to internal storage space that will be
159overwritten by subsequent calls to either function.
160.Pp
161The maximum possible precision of the return value is limited by the
162precision of a double and may not be the same on all architectures.
163.Pp
164The
165.Xr snprintf 3
166function is preferred over these functions for new code.
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
deleted file mode 100644
index a6b1d748fe..0000000000
--- a/src/lib/libc/stdlib/ecvt.c
+++ /dev/null
@@ -1,104 +0,0 @@
1/* $OpenBSD: ecvt.c,v 1.11 2019/01/25 00:19:25 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2006 Todd C. Miller <millert@openbsd.org>
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 free(s);
44 s = NULL;
45
46 if (ndigit < 0)
47 siz = -ndigit + 1;
48 else
49 siz = ndigit + 1;
50
51
52 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
53 if (value == 0.0) {
54 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
55 *sign = 0;
56 if ((rve = s = malloc(siz)) == NULL)
57 return(NULL);
58 *rve++ = '0';
59 *rve = '\0';
60 } else {
61 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
62 if (p == NULL)
63 return (NULL);
64 if (*decpt == 9999) {
65 /* Infinity or Nan, convert to inf or nan like printf */
66 *decpt = 0;
67 c = *p;
68 __freedtoa(p);
69 return(c == 'I' ? "inf" : "nan");
70 }
71 /* Make a local copy and adjust rve to be in terms of s */
72 if (pad && fmode)
73 siz += *decpt;
74 if ((s = malloc(siz)) == NULL) {
75 __freedtoa(p);
76 return(NULL);
77 }
78 (void) strlcpy(s, p, siz);
79 rve = s + (rve - p);
80 __freedtoa(p);
81 }
82
83 /* Add trailing zeros */
84 if (pad) {
85 siz -= rve - s;
86 while (--siz)
87 *rve++ = '0';
88 *rve = '\0';
89 }
90
91 return(s);
92}
93
94char *
95ecvt(double value, int ndigit, int *decpt, int *sign)
96{
97 return(__cvt(value, ndigit, decpt, sign, 0, 1));
98}
99
100char *
101fcvt(double value, int ndigit, int *decpt, int *sign)
102{
103 return(__cvt(value, ndigit, decpt, sign, 1, 1));
104}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
deleted file mode 100644
index db0529f4a0..0000000000
--- a/src/lib/libc/stdlib/erand48.c
+++ /dev/null
@@ -1,26 +0,0 @@
1/* $OpenBSD: erand48.c,v 1.5 2015/09/14 13:30:17 guenther 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 <math.h>
16#include "rand48.h"
17
18double
19erand48(unsigned short xseed[3])
20{
21 __dorand48(xseed);
22 return ldexp((double) xseed[0], -48) +
23 ldexp((double) xseed[1], -32) +
24 ldexp((double) xseed[2], -16);
25}
26DEF_WEAK(erand48);
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
deleted file mode 100644
index 22acade86c..0000000000
--- a/src/lib/libc/stdlib/exit.3
+++ /dev/null
@@ -1,102 +0,0 @@
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.18 2024/08/30 03:44:48 guenther Exp $
33.\"
34.Dd $Mdocdate: August 30 2024 $
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 -isoC-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
deleted file mode 100644
index e93d4313e3..0000000000
--- a/src/lib/libc/stdlib/exit.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/* $OpenBSD: exit.c,v 1.14 2017/08/12 22:59:52 guenther 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#include <unistd.h>
33#include "atexit.h"
34
35/*
36 * This variable is zero until a process has created a thread.
37 * It is used to avoid calling locking functions in libc when they
38 * are not required. By default, libc is intended to be(come)
39 * thread-safe, but without a (significant) penalty to non-threaded
40 * processes.
41 */
42int __isthreaded = 0;
43
44/*
45 * Exit, flushing stdio buffers if necessary.
46 */
47void
48exit(int status)
49{
50 /*
51 * Call functions registered by atexit() or _cxa_atexit()
52 * (including the stdio cleanup routine) and then _exit().
53 */
54 __cxa_finalize(NULL);
55 _exit(status);
56}
57DEF_STRONG(exit);
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
deleted file mode 100644
index d3ab1b0415..0000000000
--- a/src/lib/libc/stdlib/gcvt.c
+++ /dev/null
@@ -1,123 +0,0 @@
1/* $OpenBSD: gcvt.c,v 1.15 2022/12/27 17:10:06 jmc Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003, 2006, 2010
5 * Todd C. Miller <millert@openbsd.org>
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 formatting. */
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
deleted file mode 100644
index 5a219a5c03..0000000000
--- a/src/lib/libc/stdlib/getenv.3
+++ /dev/null
@@ -1,191 +0,0 @@
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.23 2022/08/08 22:40:03 millert Exp $
33.\"
34.Dd $Mdocdate: August 8 2022 $
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
105.Rv -std putenv setenv unsetenv
106.Pp
107The
108.Fn getenv
109function returns a pointer to the requested value, or
110.Dv NULL
111if it could not be found.
112If
113.Fn getenv
114is successful, the string returned should be considered read-only.
115.Sh ERRORS
116.Bl -tag -width Er
117.It Bq Er EINVAL
118The
119.Fn setenv
120or
121.Fn unsetenv
122function was passed an empty
123.Ar name
124or a NULL pointer, or was passed a
125.Ar name
126containing an
127.Sq =
128character.
129.Pp
130The
131.Fn putenv
132function was passed a
133.Ar string
134that did not contain an
135.Sq =
136character, or was passed a
137.Ar string
138that started with the
139.Sq =
140character.
141.It Bq Er ENOMEM
142The
143.Fn setenv
144or
145.Fn putenv
146function failed because it was unable to allocate memory for the environment.
147.El
148.Sh SEE ALSO
149.Xr csh 1 ,
150.Xr sh 1 ,
151.Xr execve 2 ,
152.Xr issetugid 2 ,
153.Xr environ 7
154.Sh STANDARDS
155The
156.Fn getenv
157function conforms to
158.St -ansiC .
159The
160.Fn putenv ,
161.Fn setenv ,
162and
163.Fn unsetenv
164functions conform to
165.St -p1003.1-2008 .
166.Sh HISTORY
167The function
168.Fn getenv
169appeared in
170.At v7
171and
172.Bx 3 .
173The functions
174.Fn setenv
175and
176.Fn unsetenv
177appeared in
178.Bx 4.3 Tahoe .
179The
180.Fn putenv
181function first appeared in
182.At V.2
183and was reimplemented for
184.Bx 4.3 Reno .
185.Sh CAVEATS
186Library code must be careful about using
187.Fn getenv
188to read untrusted environment variables in setuid programs.
189The
190.Fn issetugid
191function is provided for this purpose.
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
deleted file mode 100644
index 068d70a999..0000000000
--- a/src/lib/libc/stdlib/getenv.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/* $OpenBSD: getenv.c,v 1.13 2024/07/10 14:17:58 jca 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
34
35/*
36 * __findenv --
37 * Returns pointer to value associated with name, if any, else NULL.
38 * Starts searching within the environmental array at offset.
39 * Sets offset to be the offset of the name/value combination in the
40 * environmental array, for use by putenv(3), setenv(3) and unsetenv(3).
41 * Explicitly removes '=' in argument name.
42 */
43char *
44__findenv(const char *name, int len, int *offset)
45{
46 int i;
47 const char *np;
48 char **p, *cp;
49
50 if (name == NULL || environ == NULL)
51 return (NULL);
52 for (p = environ + *offset; (cp = *p) != NULL; ++p) {
53 for (np = name, i = len; i && *cp; i--)
54 if (*cp++ != *np++)
55 break;
56 if (i == 0 && *cp++ == '=') {
57 *offset = p - environ;
58 return (cp);
59 }
60 }
61 return (NULL);
62}
63
64/*
65 * getenv --
66 * Returns ptr to value associated with name, if any, else NULL.
67 */
68char *
69getenv(const char *name)
70{
71 int offset = 0;
72 const char *np;
73
74 for (np = name; *np && *np != '='; ++np)
75 ;
76 return (__findenv(name, (int)(np - name), &offset));
77}
78DEF_STRONG(getenv);
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
deleted file mode 100644
index c7e28ff91f..0000000000
--- a/src/lib/libc/stdlib/getopt.3
+++ /dev/null
@@ -1,365 +0,0 @@
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.48 2022/07/25 02:25:55 jsg Exp $
29.\"
30.Dd $Mdocdate: July 25 2022 $
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)) == -1)
182 err(1, "%s", optarg);
183 break;
184 default:
185 usage();
186 }
187}
188argc -= optind;
189argv += optind;
190.Ed
191.Sh DIAGNOSTICS
192If the
193.Fn getopt
194function encounters a character not found in the string
195.Fa optstring
196or detects
197a missing option argument, it writes an error message to
198.Em stderr
199and returns
200.Ql \&? .
201Setting
202.Va opterr
203to a zero will disable these error messages.
204If
205.Fa optstring
206has a leading
207.Ql \&:
208then a missing option argument causes a
209.Ql \&:
210to be returned in addition to suppressing any error messages.
211.Pp
212Option arguments are allowed to begin with
213.Ql - ;
214this is reasonable but reduces the amount of error checking possible.
215.Sh SEE ALSO
216.Xr getopt 1 ,
217.Xr getopt_long 3 ,
218.Xr getsubopt 3
219.Sh STANDARDS
220The
221.Fn getopt
222function implements a superset of the functionality specified by
223.St -p1003.1 .
224.Pp
225The following extensions are supported:
226.Bl -bullet
227.It
228The
229.Va optreset
230variable was added to make it possible to call the
231.Fn getopt
232function multiple times.
233.It
234If the
235.Va optind
236variable is set to 0,
237.Fn getopt
238will behave as if the
239.Va optreset
240variable has been set.
241This is for compatibility with
242.Tn GNU
243.Fn getopt .
244New code should use
245.Va optreset
246instead.
247.It
248If the first character of
249.Fa optstring
250is a plus sign
251.Pq Ql + ,
252it will be ignored.
253This is for compatibility with
254.Tn GNU
255.Fn getopt .
256.It
257If the first character of
258.Fa optstring
259is a dash
260.Pq Ql - ,
261non-options will be returned as arguments to the option character
262.Ql \e1 .
263This is for compatibility with
264.Tn GNU
265.Fn getopt .
266.It
267A single dash
268.Pq Ql -
269may be specified as a character in
270.Fa optstring ,
271however it should
272.Em never
273have an argument associated with it.
274This allows
275.Fn getopt
276to be used with programs that expect
277.Ql -
278as an option flag.
279This practice is wrong, and should not be used in any current development.
280It is provided for backward compatibility
281.Em only .
282Care should be taken not to use
283.Ql -
284as the first character in
285.Fa optstring
286to avoid a semantic conflict with
287.Tn GNU
288.Fn getopt
289semantics (see above).
290By default, a single dash causes
291.Fn getopt
292to return \-1.
293.El
294.Pp
295Historic
296.Bx
297versions of
298.Fn getopt
299set
300.Fa optopt
301to the last option character processed.
302However, this conflicts with
303.St -p1003.1
304which stipulates that
305.Fa optopt
306be set to the last character that caused an error.
307.Sh HISTORY
308The
309.Fn getopt
310function first appeared in
311.At III
312and was reimplemented for
313.Bx 4.3 .
314.Sh BUGS
315The
316.Fn getopt
317function was once specified to return
318.Dv EOF
319instead of \-1.
320This was changed by
321.St -p1003.2-92
322to decouple
323.Fn getopt
324from
325.In stdio.h .
326.Pp
327It is possible to handle digits as option letters.
328This allows
329.Fn getopt
330to be used with programs that expect a number
331.Pq Dq Li \-3
332as an option.
333This practice is wrong, and should not be used in any current development.
334It is provided for backward compatibility
335.Em only .
336The following code fragment works in most cases and can handle mixed
337number and letter arguments.
338.Bd -literal -offset indent
339int aflag = 0, bflag = 0, ch, lastch = '\e0';
340int length = -1, newarg = 1, prevoptind = 1;
341
342while ((ch = getopt(argc, argv, "0123456789ab")) != -1) {
343 switch (ch) {
344 case '0': case '1': case '2': case '3': case '4':
345 case '5': case '6': case '7': case '8': case '9':
346 if (newarg || !isdigit(lastch))
347 length = 0;
348 else if (length > INT_MAX / 10)
349 usage();
350 length = (length * 10) + (ch - '0');
351 break;
352 case 'a':
353 aflag = 1;
354 break;
355 case 'b':
356 bflag = 1;
357 break;
358 default:
359 usage();
360 }
361 lastch = ch;
362 newarg = optind != prevoptind;
363 prevoptind = optind;
364}
365.Ed
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
deleted file mode 100644
index 88594cbf9c..0000000000
--- a/src/lib/libc/stdlib/getopt_long.3
+++ /dev/null
@@ -1,460 +0,0 @@
1.\" $OpenBSD: getopt_long.3,v 1.25 2022/09/11 06:38:11 jmc Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. 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: September 11 2022 $
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
101By default,
102.Fn getopt_long
103permutes
104.Ar argv
105such that all option arguments are evaluated before any non-options arguments.
106If the first character of
107.Fa optstring
108is a plus sign
109.Pq Ql +
110or if the environment variable
111.Ev POSIXLY_CORRECT
112is set, then
113.Ar argv
114is processed in order and option processing stops as soon as the first
115non-option argument is encountered.
116.Pp
117The
118.Fn getopt_long
119call requires an array to be initialized describing the long
120options.
121Each element of the array is a structure:
122.Bd -literal -offset indent
123struct option {
124 char *name;
125 int has_arg;
126 int *flag;
127 int val;
128};
129.Ed
130.Pp
131The
132.Fa name
133field should contain the option name without the leading double dash.
134.Pp
135The
136.Fa has_arg
137field should be one of:
138.Pp
139.Bl -tag -width "optional_argument" -compact -offset indent
140.It Dv no_argument
141no argument to the option is expected.
142.It Dv required_argument
143an argument to the option is required.
144.It Dv optional_argument
145an argument to the option may be presented.
146.El
147.Pp
148If
149.Fa flag
150is not
151.Dv NULL ,
152then the integer pointed to by it will be set to the value in the
153.Fa val
154field.
155If the
156.Fa flag
157field is
158.Dv NULL ,
159then the
160.Fa val
161field will be returned.
162Setting
163.Fa flag
164to
165.Dv NULL
166and setting
167.Fa val
168to the corresponding short option will make this function act just
169like
170.Xr getopt 3 .
171.Pp
172If the
173.Fa longindex
174argument is not
175.Dv NULL ,
176then the integer pointed to by it will be set to the index of the long
177option relative to
178.Fa longopts .
179.Pp
180The last element of the
181.Fa longopts
182array has to be filled with zeroes.
183.Pp
184The
185.Fn getopt_long_only
186function behaves identically to
187.Fn getopt_long
188with the exception that long options may start with
189.Sq -
190in addition to
191.Sq -- .
192If an option starting with
193.Sq -
194does not match a long option but does match a single-character option,
195the single-character option is returned.
196.Sh RETURN VALUES
197If the
198.Fa flag
199field in
200.Vt struct option
201is
202.Dv NULL ,
203.Fn getopt_long
204and
205.Fn getopt_long_only
206return the value specified in the
207.Fa val
208field, which is usually just the corresponding short option.
209If
210.Fa flag
211is not
212.Dv NULL ,
213these functions return 0 and store
214.Fa val
215in the location pointed to by
216.Fa flag .
217These functions return
218.Sq \&:
219if there was a missing option argument,
220.Sq \&?
221if the user specified an unknown or ambiguous option, and
222\-1 when the argument list has been exhausted.
223.Sh IMPLEMENTATION DIFFERENCES
224This section describes differences to the GNU implementation
225found in glibc-2.1.3:
226.Bl -bullet
227.It
228handling of
229.Ql -
230within the option string (not the first character):
231.Bl -tag -width "OpenBSD"
232.It GNU
233treats a
234.Ql -
235on the command line as a non-argument.
236.It OpenBSD
237a
238.Ql -
239within the option string matches a
240.Ql -
241(single dash) on the command line.
242This functionality is provided for backward compatibility with
243programs, such as
244.Xr su 1 ,
245that use
246.Ql -
247as an option flag.
248This practice is wrong, and should not be used in any current development.
249.El
250.It
251handling of
252.Ql ::
253in the option string in the presence of
254.Ev POSIXLY_CORRECT :
255.Bl -tag -width "OpenBSD"
256.It Both
257GNU and
258.Ox
259ignore
260.Ev POSIXLY_CORRECT
261here and take
262.Ql ::
263to mean the preceding option takes an optional argument.
264.El
265.It
266return value in case of missing argument if first character
267(after
268.Ql +
269or
270.Ql - )
271in the option string is not
272.Ql \&: :
273.Bl -tag -width "OpenBSD"
274.It GNU
275returns
276.Ql \&?
277.It OpenBSD
278returns
279.Ql \&:
280(since
281.Ox Ns 's
282.Xr getopt 3
283does).
284.El
285.It
286handling of
287.Ql --a
288in
289.Xr getopt 3 :
290.Bl -tag -width "OpenBSD"
291.It GNU
292parses this as option
293.Ql - ,
294option
295.Ql a .
296.It OpenBSD
297parses this as
298.Ql -- ,
299and returns \-1 (ignoring the
300.Ql a )
301(because the original
302.Fn getopt
303did.)
304.El
305.It
306setting of
307.Va optopt
308for long options with
309.Va flag
310.No non- Ns Dv NULL :
311.Bl -tag -width "OpenBSD"
312.It GNU
313sets
314.Va optopt
315to
316.Va val .
317.It OpenBSD
318sets
319.Va optopt
320to 0 (since
321.Va val
322would never be returned).
323.El
324.It
325handling of
326.Ql -W
327with
328.Ql W;
329in the option string in
330.Xr getopt 3
331(not
332.Fn getopt_long ) :
333.Bl -tag -width "OpenBSD"
334.It GNU
335causes a segmentation fault.
336.It OpenBSD
337no special handling is done;
338.Ql W;
339is interpreted as two separate options, neither of which take an argument.
340.El
341.It
342setting of
343.Va optarg
344for long options without an argument that are invoked via
345.Ql -W
346(with
347.Ql W;
348in the option string):
349.Bl -tag -width "OpenBSD"
350.It GNU
351sets
352.Va optarg
353to the option name (the argument of
354.Ql -W ) .
355.It OpenBSD
356sets
357.Va optarg
358to
359.Dv NULL
360(the argument of the long option).
361.El
362.It
363handling of
364.Ql -W
365with an argument that is not (a prefix to) a known long option
366(with
367.Ql W;
368in the option string):
369.Bl -tag -width "OpenBSD"
370.It GNU
371returns
372.Ql -W
373with
374.Va optarg
375set to the unknown option.
376.It OpenBSD
377treats this as an error (unknown option) and returns
378.Ql \&?
379with
380.Va optopt
381set to 0 and
382.Va optarg
383set to
384.Dv NULL
385(as GNU's man page documents).
386.El
387.It
388The error messages are different.
389.It
390.Ox
391does not permute the argument vector at the same points in
392the calling sequence as GNU does.
393The aspects normally used by the caller
394(ordering after \-1 is returned, value of
395.Va optind
396relative to current positions) are the same, though.
397(We do fewer variable swaps.)
398.El
399.Sh ENVIRONMENT
400.Bl -tag -width Ev
401.It Ev POSIXLY_CORRECT
402If set, option processing stops when the first non-option is found and
403a leading
404.Sq +
405in the
406.Ar optstring
407is ignored.
408.El
409.Sh EXAMPLES
410.Bd -literal
411int bflag, ch, fd;
412int daggerset;
413
414/* options descriptor */
415static struct option longopts[] = {
416 { "buffy", no_argument, NULL, 'b' },
417 { "fluoride", required_argument, NULL, 'f' },
418 { "daggerset", no_argument, &daggerset, 1 },
419 { NULL, 0, NULL, 0 }
420};
421
422bflag = 0;
423while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
424 switch (ch) {
425 case 'b':
426 bflag = 1;
427 break;
428 case 'f':
429 if ((fd = open(optarg, O_RDONLY)) == -1)
430 err(1, "unable to open %s", optarg);
431 break;
432 case 0:
433 if (daggerset)
434 fprintf(stderr, "Buffy will use her dagger to "
435 "apply fluoride to dracula's teeth\en");
436 break;
437 default:
438 usage();
439 }
440argc -= optind;
441argv += optind;
442.Ed
443.Sh SEE ALSO
444.Xr getopt 3
445.Sh HISTORY
446The
447.Fn getopt_long
448and
449.Fn getopt_long_only
450functions first appeared in GNU libiberty.
451This implementation first appeared in
452.Ox 3.3 .
453.Sh BUGS
454The
455.Ar argv
456argument is not really
457.Dv const
458as its elements may be permuted (unless
459.Ev POSIXLY_CORRECT
460is set).
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
deleted file mode 100644
index 0de50457c2..0000000000
--- a/src/lib/libc/stdlib/getopt_long.c
+++ /dev/null
@@ -1,513 +0,0 @@
1/* $OpenBSD: getopt_long.c,v 1.32 2020/05/27 22:25:09 schwarze 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 <millert@openbsd.org>
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#if 0
65/* DEF_* only work on initialized (non-COMMON) variables */
66DEF_WEAK(opterr);
67DEF_WEAK(optind);
68DEF_WEAK(optopt);
69#endif
70
71#define PRINT_ERROR ((opterr) && (*options != ':'))
72
73#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
74#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
75#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
76
77/* return values */
78#define BADCH (int)'?'
79#define BADARG ((*options == ':') ? (int)':' : (int)'?')
80#define INORDER (int)1
81
82#define EMSG ""
83
84static int getopt_internal(int, char * const *, const char *,
85 const struct option *, int *, int);
86static int parse_long_options(char * const *, const char *,
87 const struct option *, int *, int, int);
88static int gcd(int, int);
89static void permute_args(int, int, int, char * const *);
90
91static char *place = EMSG; /* option letter processing */
92
93/* XXX: set optreset to 1 rather than these two */
94static int nonopt_start = -1; /* first non option argument (for permute) */
95static int nonopt_end = -1; /* first option after non options (for permute) */
96
97/* Error messages */
98static const char recargchar[] = "option requires an argument -- %c";
99static const char recargstring[] = "option requires an argument -- %s";
100static const char ambig[] = "ambiguous option -- %.*s";
101static const char noarg[] = "option doesn't take an argument -- %.*s";
102static const char illoptchar[] = "unknown option -- %c";
103static const char illoptstring[] = "unknown option -- %s";
104
105/*
106 * Compute the greatest common divisor of a and b.
107 */
108static int
109gcd(int a, int b)
110{
111 int c;
112
113 c = a % b;
114 while (c != 0) {
115 a = b;
116 b = c;
117 c = a % b;
118 }
119
120 return (b);
121}
122
123/*
124 * Exchange the block from nonopt_start to nonopt_end with the block
125 * from nonopt_end to opt_end (keeping the same order of arguments
126 * in each block).
127 */
128static void
129permute_args(int panonopt_start, int panonopt_end, int opt_end,
130 char * const *nargv)
131{
132 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
133 char *swap;
134
135 /*
136 * compute lengths of blocks and number and size of cycles
137 */
138 nnonopts = panonopt_end - panonopt_start;
139 nopts = opt_end - panonopt_end;
140 ncycle = gcd(nnonopts, nopts);
141 cyclelen = (opt_end - panonopt_start) / ncycle;
142
143 for (i = 0; i < ncycle; i++) {
144 cstart = panonopt_end+i;
145 pos = cstart;
146 for (j = 0; j < cyclelen; j++) {
147 if (pos >= panonopt_end)
148 pos -= nnonopts;
149 else
150 pos += nopts;
151 swap = nargv[pos];
152 ((char **)nargv)[pos] = nargv[cstart];
153 ((char **)nargv)[cstart] = swap;
154 }
155 }
156}
157
158/*
159 * parse_long_options --
160 * Parse long options in argc/argv argument vector.
161 * Returns -1 if short_too is set and the option does not match long_options.
162 */
163static int
164parse_long_options(char * const *nargv, const char *options,
165 const struct option *long_options, int *idx, int short_too, int flags)
166{
167 char *current_argv, *has_equal;
168 size_t current_argv_len;
169 int i, match, exact_match, second_partial_match;
170
171 current_argv = place;
172 match = -1;
173 exact_match = 0;
174 second_partial_match = 0;
175
176 optind++;
177
178 if ((has_equal = strchr(current_argv, '=')) != NULL) {
179 /* argument found (--option=arg) */
180 current_argv_len = has_equal - current_argv;
181 has_equal++;
182 } else
183 current_argv_len = strlen(current_argv);
184
185 for (i = 0; long_options[i].name; i++) {
186 /* find matching long option */
187 if (strncmp(current_argv, long_options[i].name,
188 current_argv_len))
189 continue;
190
191 if (strlen(long_options[i].name) == current_argv_len) {
192 /* exact match */
193 match = i;
194 exact_match = 1;
195 break;
196 }
197 /*
198 * If this is a known short option, don't allow
199 * a partial match of a single character.
200 */
201 if (short_too && current_argv_len == 1)
202 continue;
203
204 if (match == -1) /* first partial match */
205 match = i;
206 else if ((flags & FLAG_LONGONLY) ||
207 long_options[i].has_arg != long_options[match].has_arg ||
208 long_options[i].flag != long_options[match].flag ||
209 long_options[i].val != long_options[match].val)
210 second_partial_match = 1;
211 }
212 if (!exact_match && second_partial_match) {
213 /* ambiguous abbreviation */
214 if (PRINT_ERROR)
215 warnx(ambig, (int)current_argv_len, current_argv);
216 optopt = 0;
217 return (BADCH);
218 }
219 if (match != -1) { /* option found */
220 if (long_options[match].has_arg == no_argument
221 && has_equal) {
222 if (PRINT_ERROR)
223 warnx(noarg, (int)current_argv_len,
224 current_argv);
225 /*
226 * XXX: GNU sets optopt to val regardless of flag
227 */
228 if (long_options[match].flag == NULL)
229 optopt = long_options[match].val;
230 else
231 optopt = 0;
232 return (BADARG);
233 }
234 if (long_options[match].has_arg == required_argument ||
235 long_options[match].has_arg == optional_argument) {
236 if (has_equal)
237 optarg = has_equal;
238 else if (long_options[match].has_arg ==
239 required_argument) {
240 /*
241 * optional argument doesn't use next nargv
242 */
243 optarg = nargv[optind++];
244 }
245 }
246 if ((long_options[match].has_arg == required_argument)
247 && (optarg == NULL)) {
248 /*
249 * Missing argument; leading ':' indicates no error
250 * should be generated.
251 */
252 if (PRINT_ERROR)
253 warnx(recargstring,
254 current_argv);
255 /*
256 * XXX: GNU sets optopt to val regardless of flag
257 */
258 if (long_options[match].flag == NULL)
259 optopt = long_options[match].val;
260 else
261 optopt = 0;
262 --optind;
263 return (BADARG);
264 }
265 } else { /* unknown option */
266 if (short_too) {
267 --optind;
268 return (-1);
269 }
270 if (PRINT_ERROR)
271 warnx(illoptstring, current_argv);
272 optopt = 0;
273 return (BADCH);
274 }
275 if (idx)
276 *idx = match;
277 if (long_options[match].flag) {
278 *long_options[match].flag = long_options[match].val;
279 return (0);
280 } else
281 return (long_options[match].val);
282}
283
284/*
285 * getopt_internal --
286 * Parse argc/argv argument vector. Called by user level routines.
287 */
288static int
289getopt_internal(int nargc, char * const *nargv, const char *options,
290 const struct option *long_options, int *idx, int flags)
291{
292 char *oli; /* option letter list index */
293 int optchar, short_too;
294 static int posixly_correct = -1;
295
296 if (options == NULL)
297 return (-1);
298
299 /*
300 * XXX Some GNU programs (like cvs) set optind to 0 instead of
301 * XXX using optreset. Work around this braindamage.
302 */
303 if (optind == 0)
304 optind = optreset = 1;
305
306 /*
307 * Disable GNU extensions if POSIXLY_CORRECT is set or options
308 * string begins with a '+'.
309 */
310 if (posixly_correct == -1 || optreset)
311 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
312 if (*options == '-')
313 flags |= FLAG_ALLARGS;
314 else if (posixly_correct || *options == '+')
315 flags &= ~FLAG_PERMUTE;
316 if (*options == '+' || *options == '-')
317 options++;
318
319 optarg = NULL;
320 if (optreset)
321 nonopt_start = nonopt_end = -1;
322start:
323 if (optreset || !*place) { /* update scanning pointer */
324 optreset = 0;
325 if (optind >= nargc) { /* end of argument vector */
326 place = EMSG;
327 if (nonopt_end != -1) {
328 /* do permutation, if we have to */
329 permute_args(nonopt_start, nonopt_end,
330 optind, nargv);
331 optind -= nonopt_end - nonopt_start;
332 }
333 else if (nonopt_start != -1) {
334 /*
335 * If we skipped non-options, set optind
336 * to the first of them.
337 */
338 optind = nonopt_start;
339 }
340 nonopt_start = nonopt_end = -1;
341 return (-1);
342 }
343 if (*(place = nargv[optind]) != '-' ||
344 (place[1] == '\0' && strchr(options, '-') == NULL)) {
345 place = EMSG; /* found non-option */
346 if (flags & FLAG_ALLARGS) {
347 /*
348 * GNU extension:
349 * return non-option as argument to option 1
350 */
351 optarg = nargv[optind++];
352 return (INORDER);
353 }
354 if (!(flags & FLAG_PERMUTE)) {
355 /*
356 * If no permutation wanted, stop parsing
357 * at first non-option.
358 */
359 return (-1);
360 }
361 /* do permutation */
362 if (nonopt_start == -1)
363 nonopt_start = optind;
364 else if (nonopt_end != -1) {
365 permute_args(nonopt_start, nonopt_end,
366 optind, nargv);
367 nonopt_start = optind -
368 (nonopt_end - nonopt_start);
369 nonopt_end = -1;
370 }
371 optind++;
372 /* process next argument */
373 goto start;
374 }
375 if (nonopt_start != -1 && nonopt_end == -1)
376 nonopt_end = optind;
377
378 /*
379 * If we have "-" do nothing, if "--" we are done.
380 */
381 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
382 optind++;
383 place = EMSG;
384 /*
385 * We found an option (--), so if we skipped
386 * non-options, we have to permute.
387 */
388 if (nonopt_end != -1) {
389 permute_args(nonopt_start, nonopt_end,
390 optind, nargv);
391 optind -= nonopt_end - nonopt_start;
392 }
393 nonopt_start = nonopt_end = -1;
394 return (-1);
395 }
396 }
397
398 /*
399 * Check long options if:
400 * 1) we were passed some
401 * 2) the arg is not just "-"
402 * 3) either the arg starts with -- we are getopt_long_only()
403 */
404 if (long_options != NULL && place != nargv[optind] &&
405 (*place == '-' || (flags & FLAG_LONGONLY))) {
406 short_too = 0;
407 if (*place == '-')
408 place++; /* --foo long option */
409 else if (*place != ':' && strchr(options, *place) != NULL)
410 short_too = 1; /* could be short option too */
411
412 optchar = parse_long_options(nargv, options, long_options,
413 idx, short_too, flags);
414 if (optchar != -1) {
415 place = EMSG;
416 return (optchar);
417 }
418 }
419
420 if ((optchar = (int)*place++) == (int)':' ||
421 (oli = strchr(options, optchar)) == NULL) {
422 if (!*place)
423 ++optind;
424 if (PRINT_ERROR)
425 warnx(illoptchar, optchar);
426 optopt = optchar;
427 return (BADCH);
428 }
429 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
430 /* -W long-option */
431 if (*place) /* no space */
432 /* NOTHING */;
433 else if (++optind >= nargc) { /* no arg */
434 place = EMSG;
435 if (PRINT_ERROR)
436 warnx(recargchar, optchar);
437 optopt = optchar;
438 return (BADARG);
439 } else /* white space */
440 place = nargv[optind];
441 optchar = parse_long_options(nargv, options, long_options,
442 idx, 0, flags);
443 place = EMSG;
444 return (optchar);
445 }
446 if (*++oli != ':') { /* doesn't take argument */
447 if (!*place)
448 ++optind;
449 } else { /* takes (optional) argument */
450 optarg = NULL;
451 if (*place) /* no white space */
452 optarg = place;
453 else if (oli[1] != ':') { /* arg not optional */
454 if (++optind >= nargc) { /* no arg */
455 place = EMSG;
456 if (PRINT_ERROR)
457 warnx(recargchar, optchar);
458 optopt = optchar;
459 return (BADARG);
460 } else
461 optarg = nargv[optind];
462 }
463 place = EMSG;
464 ++optind;
465 }
466 /* dump back option letter */
467 return (optchar);
468}
469
470/*
471 * getopt --
472 * Parse argc/argv argument vector.
473 */
474int
475getopt(int nargc, char * const *nargv, const char *options)
476{
477
478 /*
479 * We don't pass FLAG_PERMUTE to getopt_internal() since
480 * the BSD getopt(3) (unlike GNU) has never done this.
481 *
482 * Furthermore, since many privileged programs call getopt()
483 * before dropping privileges it makes sense to keep things
484 * as simple (and bug-free) as possible.
485 */
486 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
487}
488
489/*
490 * getopt_long --
491 * Parse argc/argv argument vector.
492 */
493int
494getopt_long(int nargc, char * const *nargv, const char *options,
495 const struct option *long_options, int *idx)
496{
497
498 return (getopt_internal(nargc, nargv, options, long_options, idx,
499 FLAG_PERMUTE));
500}
501
502/*
503 * getopt_long_only --
504 * Parse argc/argv argument vector.
505 */
506int
507getopt_long_only(int nargc, char * const *nargv, const char *options,
508 const struct option *long_options, int *idx)
509{
510
511 return (getopt_internal(nargc, nargv, options, long_options, idx,
512 FLAG_PERMUTE|FLAG_LONGONLY));
513}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
deleted file mode 100644
index fee3840bef..0000000000
--- a/src/lib/libc/stdlib/getsubopt.3
+++ /dev/null
@@ -1,162 +0,0 @@
1.\" $OpenBSD: getsubopt.3,v 1.16 2022/08/04 06:20:24 jsg 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: August 4 2022 $
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
59.Dv NULL Ns -terminated
60array of pointers to strings.
61.Pp
62The
63.Fn getsubopt
64function returns the zero-based offset of the pointer in the
65.Fa tokens
66array referencing a string which matches the first token
67in the string, or \-1 if the string contains no tokens or
68.Fa tokens
69does not contain a matching string.
70.Pp
71If the token is of the form
72.Ar name Ns = Ns Ar value ,
73the location referenced by
74.Fa valuep
75will be set to point to the start of the
76.Dq value
77portion of the token.
78.Pp
79On return from
80.Fn getsubopt ,
81.Fa optionp
82will be set to point to the start of the next token in the string,
83or the NUL at the end of the string if no more tokens are present.
84The comma, space, or tab character ending the token just parsed,
85and the equal sign separating name and value if any, are replaced
86with NUL bytes in the original
87.Pf * Fa optionp
88input string.
89The external variable
90.Fa suboptarg
91will be set to point to the start of the current token, or
92.Dv NULL
93if no tokens were present.
94The argument
95.Fa valuep
96will be set to point to the value portion of the token, or
97.Dv NULL
98if no value portion was present.
99.Sh EXAMPLES
100.Bd -literal
101char *tokens[] = {
102 #define ONE 0
103 "one",
104 #define TWO 1
105 "two",
106 NULL
107};
108
109\&...
110
111extern char *optarg, *suboptarg;
112char *options, *value;
113
114while ((ch = getopt(argc, argv, "ab:")) != -1) {
115 switch (ch) {
116 case 'a':
117 /* process "a" option */
118 break;
119 case 'b':
120 options = optarg;
121 while (*options) {
122 switch (getsubopt(&options, tokens, &value)) {
123 case ONE:
124 /* process "one" sub option */
125 break;
126 case TWO:
127 /* process "two" sub option */
128 if (!value)
129 error("no value for two");
130 i = atoi(value);
131 break;
132 case -1:
133 if (suboptarg)
134 error("illegal sub option %s",
135 suboptarg);
136 else
137 error("missing sub option");
138 break;
139 }
140 }
141 break;
142 }
143}
144.Ed
145.Sh SEE ALSO
146.Xr getopt 3 ,
147.Xr strsep 3
148.Sh STANDARDS
149The
150.Fn getsubopt
151function conforms to
152.St -p1003.1-2008 .
153.Pp
154Allowing space and tab characters to separate tokens
155and the external variable
156.Va suboptarg
157are extensions to that standard.
158.Sh HISTORY
159The
160.Fn getsubopt
161function first appeared in
162.Bx 4.3 Net/2 .
diff --git a/src/lib/libc/stdlib/getsubopt.c b/src/lib/libc/stdlib/getsubopt.c
deleted file mode 100644
index 735c85ba8a..0000000000
--- a/src/lib/libc/stdlib/getsubopt.c
+++ /dev/null
@@ -1,92 +0,0 @@
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
deleted file mode 100644
index 90bde1995f..0000000000
--- a/src/lib/libc/stdlib/hcreate.3
+++ /dev/null
@@ -1,234 +0,0 @@
1.\" $OpenBSD: hcreate.3,v 1.8 2018/01/30 11:37:58 jmc 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: January 30 2018 $
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 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
162If successful, the
163.Fn hsearch
164function returns a pointer to a hash table entry matching
165the provided key.
166If the action is
167.Dv FIND
168and the item was not found, or if the action is
169.Dv ENTER
170and the insertion failed,
171.Dv NULL
172is returned and
173.Va errno
174is set to indicate the error.
175If the action is
176.Dv ENTER
177and an entry already existed in the table matching the given
178key, the existing entry is returned and is not replaced.
179.Sh ERRORS
180The
181.Fn hcreate
182and
183.Fn hsearch
184functions will fail if:
185.Bl -tag -width Er
186.It Bq Er ENOMEM
187Insufficient memory is available.
188.El
189.Sh SEE ALSO
190.Xr bsearch 3 ,
191.Xr lsearch 3 ,
192.Xr malloc 3 ,
193.Xr strcmp 3
194.Sh STANDARDS
195The
196.Fn hcreate ,
197.Fn hdestroy
198and
199.Fn hsearch
200functions conform to
201.St -xpg4.2 .
202.Sh HISTORY
203The
204.Fn hcreate ,
205.Fn hdestroy
206and
207.Fn hsearch
208functions first appeared in
209.At V .
210.Sh CAVEATS
211At least the following limitations can be mentioned:
212.Bl -bullet
213.It
214The interface permits the use of only one hash table at a time.
215.It
216Individual hash table entries can be added, but not deleted.
217.It
218The standard is indecipherable about the
219internal memory usage of the functions,
220mentioning only that
221.Do
222.Fn hcreate
223and
224.Fn hsearch
225functions may use
226.Fn malloc
227to allocate space
228.Dc .
229This limits the portability of the functions,
230given that other implementations may not
231.Xr free 3
232the buffer pointed by
233.Fa key .
234.El
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
deleted file mode 100644
index b31108a90e..0000000000
--- a/src/lib/libc/stdlib/hcreate.c
+++ /dev/null
@@ -1,189 +0,0 @@
1/* $OpenBSD: hcreate.c,v 1.7 2016/05/29 20:47:49 guenther 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 <assert.h>
51#include <errno.h>
52#include <stdint.h>
53#include <search.h>
54#include <stdlib.h>
55#include <string.h>
56#include <sys/queue.h>
57
58#include <db.h> /* for __default_hash */
59
60#ifndef _DIAGASSERT
61#define _DIAGASSERT(x)
62#endif
63
64/*
65 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
66 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
67 */
68struct internal_entry {
69 SLIST_ENTRY(internal_entry) link;
70 ENTRY ent;
71};
72SLIST_HEAD(internal_head, internal_entry);
73
74#define MIN_BUCKETS_LG2 4
75#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
76
77/*
78 * max * sizeof internal_entry must fit into size_t.
79 * assumes internal_entry is <= 32 (2^5) bytes.
80 */
81#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
82#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
83
84static struct internal_head *htable;
85static size_t htablesize;
86
87int
88hcreate(size_t nel)
89{
90 size_t idx;
91 unsigned int p2;
92
93 /* Make sure this isn't called when a table already exists. */
94 _DIAGASSERT(htable == NULL);
95 if (htable != NULL) {
96 errno = EINVAL;
97 return 0;
98 }
99
100 /* If nel is too small, make it min sized. */
101 if (nel < MIN_BUCKETS)
102 nel = MIN_BUCKETS;
103
104 /* If it's too large, cap it. */
105 if (nel > MAX_BUCKETS)
106 nel = MAX_BUCKETS;
107
108 /* If it's is not a power of two in size, round up. */
109 if ((nel & (nel - 1)) != 0) {
110 for (p2 = 0; nel != 0; p2++)
111 nel >>= 1;
112 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
113 nel = 1 << p2;
114 }
115
116 /* Allocate the table. */
117 htablesize = nel;
118 htable = calloc(htablesize, sizeof htable[0]);
119 if (htable == NULL) {
120 errno = ENOMEM;
121 return 0;
122 }
123
124 /* Initialize it. */
125 for (idx = 0; idx < htablesize; idx++)
126 SLIST_INIT(&htable[idx]);
127
128 return 1;
129}
130
131void
132hdestroy(void)
133{
134 struct internal_entry *ie;
135 size_t idx;
136
137 _DIAGASSERT(htable != NULL);
138 if (htable == NULL)
139 return;
140
141 for (idx = 0; idx < htablesize; idx++) {
142 while (!SLIST_EMPTY(&htable[idx])) {
143 ie = SLIST_FIRST(&htable[idx]);
144 SLIST_REMOVE_HEAD(&htable[idx], link);
145 free(ie->ent.key);
146 free(ie);
147 }
148 }
149 free(htable);
150 htable = NULL;
151}
152
153ENTRY *
154hsearch(ENTRY item, ACTION action)
155{
156 struct internal_head *head;
157 struct internal_entry *ie;
158 uint32_t hashval;
159 size_t len;
160
161 _DIAGASSERT(htable != NULL);
162 _DIAGASSERT(item.key != NULL);
163 _DIAGASSERT(action == ENTER || action == FIND);
164
165 len = strlen(item.key);
166 hashval = __default_hash(item.key, len);
167
168 head = &htable[hashval & (htablesize - 1)];
169 ie = SLIST_FIRST(head);
170 while (ie != NULL) {
171 if (strcmp(ie->ent.key, item.key) == 0)
172 break;
173 ie = SLIST_NEXT(ie, link);
174 }
175
176 if (ie != NULL)
177 return &ie->ent;
178 else if (action == FIND)
179 return NULL;
180
181 ie = malloc(sizeof *ie);
182 if (ie == NULL)
183 return NULL;
184 ie->ent.key = item.key;
185 ie->ent.data = item.data;
186
187 SLIST_INSERT_HEAD(head, ie, link);
188 return &ie->ent;
189}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
deleted file mode 100644
index f1db2205b0..0000000000
--- a/src/lib/libc/stdlib/heapsort.c
+++ /dev/null
@@ -1,175 +0,0 @@
1/* $OpenBSD: heapsort.c,v 1.11 2017/05/20 12:48:56 millert Exp $ */
2/*-
3 * Copyright (c) 1991, 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 * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
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 <sys/types.h>
35#include <errno.h>
36#include <stdlib.h>
37
38/*
39 * Swap two areas of size number of bytes. Although qsort(3) permits random
40 * blocks of memory to be sorted, sorting pointers is almost certainly the
41 * common case (and, were it not, could easily be made so). Regardless, it
42 * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
43 * arithmetic gets lost in the time required for comparison function calls.
44 */
45#define SWAP(a, b, count, size, tmp) { \
46 count = size; \
47 do { \
48 tmp = *a; \
49 *a++ = *b; \
50 *b++ = tmp; \
51 } while (--count); \
52}
53
54/* Copy one block of size size to another. */
55#define COPY(a, b, count, size, tmp1, tmp2) { \
56 count = size; \
57 tmp1 = a; \
58 tmp2 = b; \
59 do { \
60 *tmp1++ = *tmp2++; \
61 } while (--count); \
62}
63
64/*
65 * Build the list into a heap, where a heap is defined such that for
66 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
67 *
68 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
69 * j < nmemb, select largest of Ki, Kj and Kj+1.
70 */
71#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
72 for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
73 par_i = child_i) { \
74 child = base + child_i * size; \
75 if (child_i < nmemb && compar(child, child + size) < 0) { \
76 child += size; \
77 ++child_i; \
78 } \
79 par = base + par_i * size; \
80 if (compar(child, par) <= 0) \
81 break; \
82 SWAP(par, child, count, size, tmp); \
83 } \
84}
85
86/*
87 * Select the top of the heap and 'heapify'. Since by far the most expensive
88 * action is the call to the compar function, a considerable optimization
89 * in the average case can be achieved due to the fact that k, the displaced
90 * element, is usually quite small, so it would be preferable to first
91 * heapify, always maintaining the invariant that the larger child is copied
92 * over its parent's record.
93 *
94 * Then, starting from the *bottom* of the heap, finding k's correct place,
95 * again maintaining the invariant. As a result of the invariant no element
96 * is 'lost' when k is assigned its correct place in the heap.
97 *
98 * The time savings from this optimization are on the order of 15-20% for the
99 * average case. See Knuth, Vol. 3, page 158, problem 18.
100 *
101 * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
102 */
103#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
104 for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
105 child = base + child_i * size; \
106 if (child_i < nmemb && compar(child, child + size) < 0) { \
107 child += size; \
108 ++child_i; \
109 } \
110 par = base + par_i * size; \
111 COPY(par, child, count, size, tmp1, tmp2); \
112 } \
113 for (;;) { \
114 child_i = par_i; \
115 par_i = child_i / 2; \
116 child = base + child_i * size; \
117 par = base + par_i * size; \
118 if (child_i == 1 || compar(k, par) < 0) { \
119 COPY(child, k, count, size, tmp1, tmp2); \
120 break; \
121 } \
122 COPY(child, par, count, size, tmp1, tmp2); \
123 } \
124}
125
126/*
127 * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
128 * and worst. While heapsort is faster than the worst case of quicksort,
129 * the BSD quicksort does median selection so that the chance of finding
130 * a data set that will trigger the worst case is nonexistent. Heapsort's
131 * only advantage over quicksort is that it requires little additional memory.
132 */
133int
134heapsort(void *vbase, size_t nmemb, size_t size,
135 int (*compar)(const void *, const void *))
136{
137 size_t cnt, i, j, l;
138 char tmp, *tmp1, *tmp2;
139 char *base, *k, *p, *t;
140
141 if (nmemb <= 1)
142 return (0);
143
144 if (!size) {
145 errno = EINVAL;
146 return (-1);
147 }
148
149 if ((k = malloc(size)) == NULL)
150 return (-1);
151
152 /*
153 * Items are numbered from 1 to nmemb, so offset from size bytes
154 * below the starting address.
155 */
156 base = (char *)vbase - size;
157
158 for (l = nmemb / 2 + 1; --l;)
159 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
160
161 /*
162 * For each element of the heap, save the largest element into its
163 * final slot, save the displaced element (k), then recreate the
164 * heap.
165 */
166 while (nmemb > 1) {
167 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
168 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
169 --nmemb;
170 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
171 }
172 free(k);
173 return (0);
174}
175DEF_WEAK(heapsort);
diff --git a/src/lib/libc/stdlib/icdb.c b/src/lib/libc/stdlib/icdb.c
deleted file mode 100644
index 2ddd9db48c..0000000000
--- a/src/lib/libc/stdlib/icdb.c
+++ /dev/null
@@ -1,391 +0,0 @@
1/* $OpenBSD: icdb.c,v 1.8 2016/09/04 16:56:02 nicm Exp $ */
2/*
3 * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
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
18#include <errno.h>
19#include <fcntl.h>
20#include <icdb.h>
21#include <stddef.h>
22#include <stdint.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include <sys/mman.h>
29#include <sys/stat.h>
30
31#include <siphash.h>
32
33/*
34 * Creating a new icdb: icdb_new
35 * Opening existing icdb: icdb_open
36 *
37 * Adding new entries: icdb_add
38 * Adding entries does not update the disk or indices.
39 *
40 * Save to disk: icdb_save
41 * Update indices: icdb_rehash
42 * icdb_save will call rehash.
43 *
44 * Change an existing entry: icdb_update
45 * Changing entries does write to disk.
46 *
47 * Find an entry: icdb_lookup
48 * Looking up an entry is only defined when the indices are synced.
49 *
50 * Close and free resources: icdb_close
51 */
52
53/*
54 * There are two major modes of operation.
55 *
56 * Existing databases use the mmap codepath. The entire database is mapped
57 * into the address space for quick access. Individual entries may be updated,
58 * but no new entries added.
59 *
60 * New databases use malloc backed memory instead. The database may be saved
61 * with icdb_save. It should be saved to a new file to avoid corrupting any
62 * open databases in other processes.
63 */
64
65/*
66 * An icdb has the following format:
67 * struct icbinfo header
68 * indexes [ uint32_t * indexsize * nkeys ]
69 * entries [ entrysize * nentries ]
70 *
71 * To find an entry in the file, the user specifies which key to use.
72 * The key is hashed and looked up in the index. The index contains the
73 * position of the entry in the entries array. -1 identifies not found.
74 * Chaining is done by rehashing the hash. All keys are fixed size byte arrays.
75 */
76
77/*
78 * Header info for icdb. This struct is stored on disk.
79 */
80struct icdbinfo {
81 uint32_t magic; /* magic */
82 uint32_t version; /* user specified version */
83 uint32_t nentries; /* number of entries stored */
84 uint32_t entrysize; /* size of each entry */
85 uint32_t indexsize; /* number of entries in hash index */
86 uint32_t nkeys; /* number of keys defined */
87 uint32_t keysize[8]; /* size of each key */
88 uint32_t keyoffset[8]; /* offset of each key in entry */
89 SIPHASH_KEY siphashkey; /* random hash key */
90};
91
92/*
93 * In memory representation with auxiliary data.
94 * idxdata and entries will be written to disk after info.
95 */
96struct icdb {
97 struct icdbinfo *info;
98 void *idxdata[8];
99 void *entries;
100 size_t maplen;
101 uint32_t allocated;
102 int fd;
103};
104
105static const uint32_t magic = 0x1ca9d0b7;
106
107static uint32_t
108roundup(uint32_t num)
109{
110 uint32_t r = 2;
111
112 while (r < num * 3 / 2)
113 r *= 2;
114 return r;
115}
116
117struct icdb *
118icdb_new(uint32_t version, uint32_t nentries, uint32_t entrysize,
119 uint32_t nkeys, const uint32_t *keysizes, const uint32_t *keyoffsets)
120{
121 struct icdb *db;
122 struct icdbinfo *info;
123 int i;
124
125 if (entrysize == 0 || entrysize > 1048576 || nkeys > 8) {
126 errno = EINVAL;
127 return NULL;
128 }
129
130 if (!(db = calloc(1, sizeof(*db))))
131 return NULL;
132 if (!(info = calloc(1, sizeof(*info)))) {
133 free(db);
134 return NULL;
135 }
136 db->info = info;
137 db->fd = -1;
138 info->magic = magic;
139 info->version = version;
140 if (nentries)
141 if ((db->entries = reallocarray(NULL, nentries, entrysize)))
142 db->allocated = nentries;
143 info->entrysize = entrysize;
144 info->nkeys = nkeys;
145 for (i = 0; i < nkeys; i++) {
146 info->keysize[i] = keysizes[i];
147 info->keyoffset[i] = keyoffsets[i];
148 }
149 return db;
150}
151DEF_WEAK(icdb_new);
152
153struct icdb *
154icdb_open(const char *name, int flags, uint32_t version)
155{
156 struct icdb *db = NULL;
157 struct icdbinfo *info;
158 struct stat sb;
159 uint8_t *ptr = MAP_FAILED;
160 uint32_t baseoff, indexsize, idxmask, idxlen;
161 int fd, i, saved_errno;
162
163 if ((fd = open(name, flags | O_CLOEXEC)) == -1)
164 return NULL;
165 if (fstat(fd, &sb) != 0)
166 goto fail;
167 if (sb.st_size < sizeof(struct icdbinfo))
168 goto fail;
169 ptr = mmap(NULL, sb.st_size, PROT_READ |
170 ((flags & O_RDWR) ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
171 if (ptr == MAP_FAILED)
172 goto fail;
173 info = (struct icdbinfo *)ptr;
174 if (info->magic != magic || info->version != version) {
175 errno = ENOENT;
176 goto fail;
177 }
178
179 if (!(db = calloc(1, sizeof(*db))))
180 goto fail;
181 db->info = info;
182
183 indexsize = info->indexsize;
184 idxmask = indexsize - 1;
185 idxlen = indexsize * sizeof(uint32_t);
186 baseoff = sizeof(*info) + idxlen * info->nkeys;
187
188 for (i = 0; i < info->nkeys; i++)
189 db->idxdata[i] = ptr + sizeof(*info) + i * idxlen;
190 db->entries = ptr + baseoff;
191 db->maplen = sb.st_size;
192 db->fd = fd;
193 return db;
194
195fail:
196 saved_errno = errno;
197 if (ptr != MAP_FAILED)
198 munmap(ptr, sb.st_size);
199 if (fd != -1)
200 close(fd);
201 free(db);
202 errno = saved_errno;
203 return NULL;
204}
205DEF_WEAK(icdb_open);
206
207int
208icdb_get(struct icdb *db, void *entry, uint32_t idx)
209{
210 uint32_t entrysize = db->info->entrysize;
211
212 memcpy(entry, (uint8_t *)db->entries + idx * entrysize, entrysize);
213 return 0;
214}
215DEF_WEAK(icdb_get);
216
217int
218icdb_lookup(struct icdb *db, int keynum, const void *key, void *entry,
219 uint32_t *idxp)
220{
221 struct icdbinfo *info = db->info;
222 uint32_t offset;
223 uint64_t hash;
224 uint32_t indexsize, idxmask, idxlen;
225 uint32_t *idxdata;
226
227 indexsize = info->indexsize;
228 idxmask = indexsize - 1;
229 idxlen = indexsize * sizeof(uint32_t);
230
231 idxdata = db->idxdata[keynum];
232
233 hash = SipHash24(&info->siphashkey, key, info->keysize[keynum]);
234 while ((offset = idxdata[hash & idxmask]) != -1) {
235 if (icdb_get(db, entry, offset) != 0) {
236 errno = ENOENT;
237 return -1;
238 }
239 if (memcmp((uint8_t *)entry + info->keyoffset[keynum], key,
240 info->keysize[keynum]) == 0) {
241 if (idxp)
242 *idxp = offset;
243 return 0;
244 }
245 hash = SipHash24(&info->siphashkey, &hash, sizeof(hash));
246 }
247 return 1;
248}
249DEF_WEAK(icdb_lookup);
250
251int
252icdb_nentries(struct icdb *db)
253{
254 return db->info->nentries;
255}
256DEF_WEAK(icdb_nentries);
257
258const void *
259icdb_entries(struct icdb *db)
260{
261 return db->entries;
262}
263DEF_WEAK(icdb_entries);
264
265int
266icdb_update(struct icdb *db, const void *entry, int offset)
267{
268 struct icdbinfo *info = db->info;
269 uint32_t entrysize = info->entrysize;
270 uint32_t baseoff;
271 uint32_t indexsize, idxmask, idxlen;
272
273 indexsize = info->indexsize;
274 idxmask = indexsize - 1;
275 idxlen = indexsize * sizeof(uint32_t);
276 baseoff = sizeof(*info) + idxlen * info->nkeys;
277
278 memcpy((uint8_t *)db->entries + offset * entrysize, entry, entrysize);
279 if (db->fd != -1) {
280 msync((uint8_t *)db->entries + offset * entrysize, entrysize,
281 MS_SYNC);
282 }
283 return 0;
284}
285DEF_WEAK(icdb_update);
286
287int
288icdb_add(struct icdb *db, const void *entry)
289{
290 struct icdbinfo *info = db->info;
291 size_t entrysize = info->entrysize;
292
293 if (db->allocated == info->nentries) {
294 void *p;
295 size_t amt = db->allocated ? db->allocated * 2 : 63;
296 if (!(p = reallocarray(db->entries, amt, entrysize)))
297 return -1;
298 db->allocated = amt;
299 db->entries = p;
300 }
301 memcpy((uint8_t *)db->entries + info->nentries * entrysize,
302 entry, entrysize);
303 info->nentries++;
304 return 0;
305}
306DEF_WEAK(icdb_add);
307
308int
309icdb_rehash(struct icdb *db)
310{
311 struct icdbinfo *info = db->info;
312 uint32_t entrysize = info->entrysize;
313 uint32_t indexsize, idxmask, idxlen;
314 int i, j;
315
316 indexsize = info->indexsize = roundup(info->nentries);
317 idxmask = indexsize - 1;
318 idxlen = sizeof(uint32_t) * indexsize;
319
320 arc4random_buf(&info->siphashkey, sizeof(info->siphashkey));
321
322 for (i = 0; i < info->nkeys; i++) {
323 uint32_t *idxdata = reallocarray(db->idxdata[i],
324 indexsize, sizeof(uint32_t));
325 if (!idxdata)
326 return -1;
327 memset(idxdata, 0xff, idxlen);
328 db->idxdata[i] = idxdata;
329 }
330 for (j = 0; j < info->nentries; j++) {
331 for (i = 0; i < info->nkeys; i++) {
332 uint32_t *idxdata = db->idxdata[i];
333 uint64_t hash = SipHash24(&info->siphashkey,
334 (uint8_t *)db->entries + j * entrysize +
335 info->keyoffset[i], info->keysize[i]);
336 while (idxdata[hash & idxmask] != -1)
337 hash = SipHash24(&info->siphashkey, &hash, sizeof(hash));
338 idxdata[hash & idxmask] = j;
339 }
340 }
341 return 0;
342}
343DEF_WEAK(icdb_rehash);
344
345int
346icdb_save(struct icdb *db, int fd)
347{
348 struct icdbinfo *info = db->info;
349 uint32_t entrysize = info->entrysize;
350 uint32_t indexsize, idxlen;
351 int i;
352
353 if (icdb_rehash(db) != 0)
354 return -1;
355
356 indexsize = info->indexsize;
357 idxlen = sizeof(uint32_t) * indexsize;
358
359 if (ftruncate(fd, 0) != 0)
360 return -1;
361 if (write(fd, info, sizeof(*info)) != sizeof(*info))
362 return -1;
363 for (i = 0; i < info->nkeys; i++) {
364 if (write(fd, db->idxdata[i], idxlen) != idxlen)
365 return -1;
366 }
367 if (write(fd, db->entries, info->nentries * entrysize) !=
368 info->nentries * entrysize)
369 return -1;
370 return 0;
371}
372DEF_WEAK(icdb_save);
373
374int
375icdb_close(struct icdb *db)
376{
377 int i;
378
379 if (db->fd == -1) {
380 for (i = 0; i < db->info->nkeys; i++)
381 free(db->idxdata[i]);
382 free(db->entries);
383 free(db->info);
384 } else {
385 munmap(db->info, db->maplen);
386 close(db->fd);
387 }
388 free(db);
389 return 0;
390}
391DEF_WEAK(icdb_close);
diff --git a/src/lib/libc/stdlib/icdb_new.3 b/src/lib/libc/stdlib/icdb_new.3
deleted file mode 100644
index 9fc07bda80..0000000000
--- a/src/lib/libc/stdlib/icdb_new.3
+++ /dev/null
@@ -1,68 +0,0 @@
1.\" $OpenBSD: icdb_new.3,v 1.2 2016/09/04 19:05:09 jmc Exp $
2.\"
3.\" Copyright (c) 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.\"
18.Dd $Mdocdate: September 4 2016 $
19.Dt ICBB_NEW 3
20.Os
21.Sh NAME
22.Nm icdb_new ,
23.Nm icdb_open ,
24.Nm icdb_get ,
25.Nm icdb_lookup ,
26.Nm icdb_nentries ,
27.Nm icdb_entries ,
28.Nm icdb_update ,
29.Nm icdb_add ,
30.Nm icdb_rehash ,
31.Nm icdb_save ,
32.Nm icdb_close
33.Nd simple database
34.Sh SYNOPSIS
35.In icbd.h
36.Ft struct icdb *
37.Fn icdb_new "uint32_t version" "uint32_t nentries" "uint32_t entrysize"
38.Ft struct icdb *
39.Fn icdb_open "const char *name" "int flags" "uint32_t version"
40.Ft int
41.Fn icdb_get "struct icdb *db" "void *entry" "uint32_t idx"
42.Ft int
43.Fn icdb_lookup "struct icdb *db" "int keynum" "const void *key" "void *entry" "uint32_t *idxp"
44.Ft int
45.Fn icdb_nentries "struct icdb *db"
46.Ft const void *
47.Fn icdb_entries "struct icdb *db"
48.Ft int
49.Fn icdb_update "struct icdb *db" "const void *entry" "int offset"
50.Ft int
51.Fn icdb_add "struct icdb *db" "const void *entry"
52.Ft int
53.Fn icdb_rehash "struct icdb *db"
54.Ft int
55.Fn icdb_save "struct icdb *db" "int fd"
56.Ft int
57.Fn icdb_close "struct icdb *db"
58.Sh DESCRIPTION
59These functions provide access to a simple memory mapped database format.
60.Sh EXAMPLES
61Look how easy it is to use.
62.Sh STANDARDS
63These functions are not standardized.
64.Sh HISTORY
65The icdb functions were introduced in
66.Ox 6.0 .
67.Sh AUTHORS
68.An Ted Unangst Aq Mt tedu@openbsd.org
diff --git a/src/lib/libc/stdlib/imaxabs.3 b/src/lib/libc/stdlib/imaxabs.3
deleted file mode 100644
index 340be61b6e..0000000000
--- a/src/lib/libc/stdlib/imaxabs.3
+++ /dev/null
@@ -1,70 +0,0 @@
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.8 2019/01/18 07:32:17 schwarze Exp $
33.\"
34.Dd $Mdocdate: January 18 2019 $
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.In stdint.h
43.Ft intmax_t
44.Fn imaxabs "intmax_t j"
45.Sh DESCRIPTION
46The
47.Fn imaxabs
48function computes the absolute value of the intmax_t variable
49.Fa j .
50.Sh RETURN VALUES
51The
52.Fn imaxabs
53function returns the absolute value.
54.Sh SEE ALSO
55.Xr abs 3 ,
56.Xr cabs 3 ,
57.Xr floor 3 ,
58.Xr hypot 3 ,
59.Xr labs 3
60.Sh STANDARDS
61The
62.Fn imaxabs
63function conforms to
64.St -isoC-99 .
65.Sh CAVEATS
66The result of applying
67.Fn imaxabs
68to
69.Dv INTMAX_MIN
70is undefined.
diff --git a/src/lib/libc/stdlib/imaxabs.c b/src/lib/libc/stdlib/imaxabs.c
deleted file mode 100644
index b7e910eefd..0000000000
--- a/src/lib/libc/stdlib/imaxabs.c
+++ /dev/null
@@ -1,38 +0,0 @@
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
deleted file mode 100644
index 70168acb30..0000000000
--- a/src/lib/libc/stdlib/imaxdiv.3
+++ /dev/null
@@ -1,65 +0,0 @@
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.8 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
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.Vt imaxdiv_t
51that contains two
52.Vt 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.Sh STANDARDS
62The
63.Fn imaxdiv
64function conforms to
65.St -isoC-99 .
diff --git a/src/lib/libc/stdlib/imaxdiv.c b/src/lib/libc/stdlib/imaxdiv.c
deleted file mode 100644
index 0515a94b96..0000000000
--- a/src/lib/libc/stdlib/imaxdiv.c
+++ /dev/null
@@ -1,50 +0,0 @@
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
deleted file mode 100644
index 136c08bad8..0000000000
--- a/src/lib/libc/stdlib/insque.3
+++ /dev/null
@@ -1,103 +0,0 @@
1.\" $OpenBSD: insque.3,v 1.12 2020/04/26 16:36:14 schwarze 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: April 26 2020 $
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd legacy doubly linked lists
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 a legacy variety of intrusive doubly linked lists.
53A list can be either circular or linear.
54Each element in the list 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 members of the struct must be pointers of the
64same type that point to the next and previous elements in
65the list, respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a list immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the list.
80.Pp
81These functions are not atomic.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn insque
87and
88.Fn remque
89functions conform to the X/Open System Interfaces option of the
90.St -p1003.1-2008
91specification.
92.Sh HISTORY
93The
94.Fn insque
95and
96.Fn remque
97functions are derived from the
98.Li insque
99and
100.Li remque
101instructions on the VAX.
102They first appeared in
103.Bx 4.2 .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
deleted file mode 100644
index 590ff837b8..0000000000
--- a/src/lib/libc/stdlib/insque.c
+++ /dev/null
@@ -1,54 +0,0 @@
1/* $OpenBSD: insque.c,v 1.3 2014/08/15 04:14:36 guenther 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 <stdlib.h>
32#include <search.h>
33
34struct qelem {
35 struct qelem *q_forw;
36 struct qelem *q_back;
37};
38
39void
40insque(void *entry, void *pred)
41{
42 struct qelem *e = entry;
43 struct qelem *p = pred;
44
45 if (p == NULL)
46 e->q_forw = e->q_back = NULL;
47 else {
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 if (p->q_forw != NULL)
51 p->q_forw->q_back = e;
52 p->q_forw = e;
53 }
54}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
deleted file mode 100644
index cb8c592750..0000000000
--- a/src/lib/libc/stdlib/jrand48.c
+++ /dev/null
@@ -1,22 +0,0 @@
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
deleted file mode 100644
index 4f33df37b2..0000000000
--- a/src/lib/libc/stdlib/l64a.c
+++ /dev/null
@@ -1,42 +0,0 @@
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
deleted file mode 100644
index f3fd6fd528..0000000000
--- a/src/lib/libc/stdlib/labs.3
+++ /dev/null
@@ -1,88 +0,0 @@
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.17 2019/01/18 07:32:17 schwarze Exp $
33.\"
34.Dd $Mdocdate: January 18 2019 $
35.Dt LABS 3
36.Os
37.Sh NAME
38.Nm labs ,
39.Nm llabs ,
40.Nm qabs
41.Nd return the absolute value of a long integer
42.Sh SYNOPSIS
43.In limits.h
44.In stdlib.h
45.Ft long
46.Fn labs "long i"
47.Ft long long
48.Fn llabs "long long j"
49.Ft quad_t
50.Fn qabs "quad_t j"
51.Sh DESCRIPTION
52The
53.Fn labs
54function returns the absolute value of the long integer
55.Fa i .
56The
57.Fn llabs
58function returns the absolute value of the long long integer
59.Fa j .
60.Pp
61The
62.Fn qabs
63function is a deprecated equivalent of
64.Fn llabs .
65.Sh SEE ALSO
66.Xr abs 3 ,
67.Xr cabs 3 ,
68.Xr floor 3 ,
69.Xr imaxabs 3
70.Sh STANDARDS
71The
72.Fn labs
73and
74.Fn llabs
75functions conform to
76.St -isoC-99 .
77.Sh CAVEATS
78The results of applying
79.Fn labs
80to
81.Dv LONG_MIN
82and
83.Fn llabs
84to
85.Dv LLONG_MIN
86are undefined, and
87.Fn qabs
88is not portable in the first place.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
deleted file mode 100644
index ca60b9aba2..0000000000
--- a/src/lib/libc/stdlib/labs.c
+++ /dev/null
@@ -1,37 +0,0 @@
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
deleted file mode 100644
index f03083e3c8..0000000000
--- a/src/lib/libc/stdlib/lcong48.c
+++ /dev/null
@@ -1,36 +0,0 @@
1/* $OpenBSD: lcong48.c,v 1.6 2015/09/13 08:31:47 guenther 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
17void
18lcong48(unsigned short p[7])
19{
20 lcong48_deterministic(p);
21 __rand48_deterministic = 0;
22}
23
24void
25lcong48_deterministic(unsigned short p[7])
26{
27 __rand48_deterministic = 1;
28 __rand48_seed[0] = p[0];
29 __rand48_seed[1] = p[1];
30 __rand48_seed[2] = p[2];
31 __rand48_mult[0] = p[3];
32 __rand48_mult[1] = p[4];
33 __rand48_mult[2] = p[5];
34 __rand48_add = p[6];
35}
36DEF_WEAK(lcong48_deterministic);
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
deleted file mode 100644
index c7ddc85ac5..0000000000
--- a/src/lib/libc/stdlib/ldiv.3
+++ /dev/null
@@ -1,71 +0,0 @@
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.14 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
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.Vt ldiv_t
51that contains two
52.Vt 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.Sh STANDARDS
62The
63.Fn ldiv
64function conforms to
65.St -ansiC .
66.Sh HISTORY
67An
68.Fn ldiv
69function with similar functionality, but a different calling convention,
70first appeared in
71.At v4 .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
deleted file mode 100644
index 775065f525..0000000000
--- a/src/lib/libc/stdlib/ldiv.c
+++ /dev/null
@@ -1,50 +0,0 @@
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
deleted file mode 100644
index f4a260f4a8..0000000000
--- a/src/lib/libc/stdlib/llabs.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/* $OpenBSD: llabs.c,v 1.4 2016/08/14 23:18:03 guenther 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}
39
40__weak_alias(qabs, llabs);
diff --git a/src/lib/libc/stdlib/lldiv.3 b/src/lib/libc/stdlib/lldiv.3
deleted file mode 100644
index 539d7b5179..0000000000
--- a/src/lib/libc/stdlib/lldiv.3
+++ /dev/null
@@ -1,73 +0,0 @@
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.9 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
35.Dt LLDIV 3
36.Os
37.Sh NAME
38.Nm lldiv ,
39.Nm qdiv
40.Nd return quotient and remainder from division
41.Sh SYNOPSIS
42.In stdlib.h
43.Ft lldiv_t
44.Fn lldiv "long long num" "long long denom"
45.Ft qdiv_t
46.Fn qdiv "quad_t num" "quad_t denom"
47.Sh DESCRIPTION
48The
49.Fn lldiv
50function computes the value
51.Fa num Ns / Ns Fa denom
52and returns the quotient and remainder in a structure named
53.Vt lldiv_t
54that contains two
55.Vt long long integer
56members named
57.Fa quot
58and
59.Fa rem .
60.Pp
61The
62.Fn qdiv
63function is a deprecated equivalent of
64.Fn lldiv .
65.Sh SEE ALSO
66.Xr div 3 ,
67.Xr imaxdiv 3 ,
68.Xr ldiv 3
69.Sh STANDARDS
70The
71.Fn lldiv
72function conforms to
73.St -isoC-99 .
diff --git a/src/lib/libc/stdlib/lldiv.c b/src/lib/libc/stdlib/lldiv.c
deleted file mode 100644
index 59c37b878c..0000000000
--- a/src/lib/libc/stdlib/lldiv.c
+++ /dev/null
@@ -1,52 +0,0 @@
1/* $OpenBSD: lldiv.c,v 1.2 2016/08/14 23:18:03 guenther 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}
51
52__weak_alias(qdiv, lldiv);
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
deleted file mode 100644
index 142cca7f78..0000000000
--- a/src/lib/libc/stdlib/lrand48.c
+++ /dev/null
@@ -1,24 +0,0 @@
1/* $OpenBSD: lrand48.c,v 1.5 2015/08/27 04:33:31 guenther 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
18lrand48(void)
19{
20 if (__rand48_deterministic == 0)
21 return arc4random() & 0x7fffffff;
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
deleted file mode 100644
index d82c55c859..0000000000
--- a/src/lib/libc/stdlib/lsearch.3
+++ /dev/null
@@ -1,106 +0,0 @@
1.\" $OpenBSD: lsearch.3,v 1.14 2015/11/30 17:03:05 jmc 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: November 30 2015 $
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 void *
42.Fn lsearch "const void *key" "void *base" "size_t *nelp" \
43 "size_t width" "int (*compar)(const void *, const void *)"
44.Ft void *
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 dbopen 3
99.Sh STANDARDS
100The
101.Fn lsearch
102and
103.Fn lfind
104functions conform to the X/Open System Interfaces option of the
105.St -p1003.1-2008
106specification.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
deleted file mode 100644
index 95ebf49b81..0000000000
--- a/src/lib/libc/stdlib/lsearch.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* $OpenBSD: lsearch.c,v 1.7 2021/12/08 22:06:28 cheloha 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 *);
40
41void *
42lsearch(const void *key, void *base, size_t *nelp, size_t width,
43 cmp_fn_t compar)
44{
45 void *element = lfind(key, base, nelp, width, compar);
46
47 /*
48 * Use memmove(3) to ensure the key is copied cleanly into the
49 * array, even if the key overlaps with the end of the array.
50 */
51 if (element == NULL) {
52 element = memmove((char *)base + *nelp * width, key, width);
53 *nelp += 1;
54 }
55 return element;
56}
57
58void *
59lfind(const void *key, const void *base, size_t *nelp, size_t width,
60 cmp_fn_t compar)
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 return NULL;
69}
70DEF_WEAK(lfind);
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
deleted file mode 100644
index bea5575bf8..0000000000
--- a/src/lib/libc/stdlib/malloc.3
+++ /dev/null
@@ -1,860 +0,0 @@
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.142 2024/08/03 20:09:24 guenther Exp $
34.\"
35.Dd $Mdocdate: August 3 2024 $
36.Dt MALLOC 3
37.Os
38.Sh NAME
39.Nm malloc ,
40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm reallocarray ,
44.Nm recallocarray ,
45.Nm freezero ,
46.Nm aligned_alloc ,
47.Nm malloc_conceal ,
48.Nm calloc_conceal
49.Nd memory allocation and deallocation
50.Sh SYNOPSIS
51.In stdlib.h
52.Ft void *
53.Fn malloc "size_t size"
54.Ft void *
55.Fn calloc "size_t nmemb" "size_t size"
56.Ft void *
57.Fn realloc "void *ptr" "size_t size"
58.Ft void
59.Fn free "void *ptr"
60.Ft void *
61.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
62.Ft void *
63.Fn recallocarray "void *ptr" "size_t oldnmemb" "size_t nmemb" "size_t size"
64.Ft void
65.Fn freezero "void *ptr" "size_t size"
66.Ft void *
67.Fn aligned_alloc "size_t alignment" "size_t size"
68.Ft void *
69.Fn malloc_conceal "size_t size"
70.Ft void *
71.Fn calloc_conceal "size_t nmemb" "size_t size"
72.Vt char *malloc_options ;
73.Sh DESCRIPTION
74The standard functions
75.Fn malloc ,
76.Fn calloc ,
77and
78.Fn realloc
79allocate
80.Em objects ,
81regions of memory to store values.
82The
83.Fn malloc
84function allocates uninitialized space for an object of
85the specified
86.Fa size .
87.Fn malloc
88maintains multiple lists of free objects according to size, allocating
89from the appropriate list or requesting memory from the kernel.
90The allocated space is suitably aligned (after possible pointer coercion) for
91storage of any type of object.
92.Pp
93The
94.Fn calloc
95function allocates space for an array of
96.Fa nmemb
97objects, each of the specified
98.Fa size .
99The space is initialized to zero.
100.Pp
101The
102.Fn realloc
103function changes the size of the object pointed to by
104.Fa ptr
105to
106.Fa size
107bytes and returns a pointer to the (possibly moved) object.
108If
109.Fa ptr
110is not
111.Dv NULL ,
112it must be a pointer returned by an earlier call to an allocation or
113reallocation function that was not freed in between.
114The contents of the object are unchanged up to the lesser
115of the new and old sizes.
116If the new size is larger, the value of the newly allocated portion
117of the object is indeterminate and uninitialized.
118If the space cannot be allocated, the object
119pointed to by
120.Fa ptr
121is unchanged.
122If
123.Fa ptr
124is
125.Dv NULL ,
126.Fn realloc
127behaves like
128.Fn malloc
129and allocates a new object.
130.Pp
131The
132.Fn free
133function causes the space pointed to by
134.Fa ptr
135to be either placed on a list of free blocks to make it available for future
136allocation or, when appropriate, to be returned to the kernel using
137.Xr munmap 2 .
138If
139.Fa ptr
140is
141.Dv NULL ,
142no action occurs.
143If
144.Fa ptr
145was previously freed by
146.Fn free
147or a reallocation function,
148the behavior is undefined and the double free is a security concern.
149.Pp
150Designed for safe allocation of arrays,
151the
152.Fn reallocarray
153function is similar to
154.Fn realloc
155except it operates on
156.Fa nmemb
157members of size
158.Fa size
159and checks for integer overflow in the calculation
160.Fa nmemb
161*
162.Fa size .
163.Pp
164Used for the allocation of memory holding sensitive data,
165the
166.Fn recallocarray
167and
168.Fn freezero
169functions guarantee that memory becoming unallocated is explicitly
170.Em discarded ,
171meaning pages of memory are disposed via
172.Xr munmap 2
173and cached free objects are cleared with
174.Xr explicit_bzero 3 .
175.Pp
176The
177.Fn recallocarray
178function is similar to
179.Fn reallocarray
180except it ensures newly allocated memory is cleared similar to
181.Fn calloc .
182If
183.Fa ptr
184is
185.Dv NULL ,
186.Fa oldnmemb
187is ignored and the call is equivalent to
188.Fn calloc .
189If
190.Fa ptr
191is not
192.Dv NULL ,
193.Fa oldnmemb
194must be a value such that
195.Fa oldnmemb
196*
197.Fa size
198is the size of the earlier allocation that returned
199.Fa ptr ,
200otherwise the behavior is undefined.
201.Pp
202The
203.Fn freezero
204function is similar to the
205.Fn free
206function except it ensures memory is explicitly discarded.
207If
208.Fa ptr
209is
210.Dv NULL ,
211no action occurs.
212If
213.Fa ptr
214is not
215.Dv NULL ,
216the
217.Fa size
218argument must be equal to or smaller than the size of the earlier allocation
219that returned
220.Fa ptr .
221.Fn freezero
222guarantees the memory range starting at
223.Fa ptr
224with length
225.Fa size
226is discarded while deallocating the whole object originally allocated.
227.Pp
228The
229.Fn aligned_alloc
230function allocates
231.Fa size
232bytes of memory such that the allocation's base address is a multiple of
233.Fa alignment .
234The requested
235.Fa alignment
236must be a power of 2.
237If
238.Fa size
239is not a multiple of
240.Fa alignment ,
241behavior is undefined.
242.Pp
243The
244.Fn malloc_conceal
245and
246.Fn calloc_conceal
247functions behave the same as
248.Fn malloc
249and
250.Fn calloc
251respectively,
252with the exception that the allocation returned is marked with the
253.Dv MAP_CONCEAL
254.Xr mmap 2
255flag and calling
256.Fn free
257on the allocation will discard the contents explicitly.
258A reallocation of a concealed allocation will leave these properties intact.
259.Sh MALLOC OPTIONS
260Upon the first call to the
261.Fn malloc
262family of functions, an initialization sequence inspects the
263value of the
264.Va vm.malloc_conf
265.Xr sysctl 2 ,
266next checks the environment for a variable called
267.Ev MALLOC_OPTIONS ,
268and finally looks at the global variable
269.Va malloc_options
270in the program.
271Each is scanned for the flags documented below.
272Unless otherwise noted uppercase means on, lowercase means off.
273During initialization, flags occurring later modify the behaviour
274that was requested by flags processed earlier.
275.Bl -tag -width indent
276.It Cm C
277.Dq Canaries .
278Add canaries at the end of allocations in order to detect
279heap overflows.
280The canary's content is checked when
281.Nm free
282is called.
283If it has been corrupted, the process is aborted.
284.It Cm D
285.Dq Dump .
286.Fn malloc
287will dump a leak report using
288.Xr utrace 2
289at exit.
290To record the dump:
291.Pp
292.Dl $ MALLOC_OPTIONS=D ktrace -tu program ...
293.Pp
294To view the leak report:
295.Pp
296.Dl $ kdump -u malloc ...
297.Pp
298By default, the immediate caller of a
299.Nm
300function will be recorded.
301Use malloc option
302.Cm 2 ,
303.Cm 3
304or
305.Cm 4
306to record deeper call stacks.
307These malloc options imply
308.Cm D .
309.It Cm F
310.Dq Freecheck .
311Enable more extensive double free and write after free detection.
312All chunks in the delayed free list will be checked for double frees and
313write after frees.
314Unused pages on the freelist are read and write protected to
315cause a segmentation fault upon access.
316.It Cm G
317.Dq Guard .
318Enable guard pages.
319Each page size or larger allocation is followed by a guard page that will
320cause a segmentation fault upon any access.
321.It Cm J
322.Dq More junking .
323Increase the junk level by one if it is smaller than 2.
324.It Cm j
325.Dq Less junking .
326Decrease the junk level by one if it is larger than 0.
327Junking writes some junk bytes into the area allocated.
328Junk is bytes of 0xdb when allocating;
329small allocations are initially junked with 0xdf as are freed allocations.
330By default the junk level is 1: after free,
331small chunks are completely junked;
332for pages the first part is junked.
333After a delay,
334the filling pattern is validated and the process is aborted if the pattern
335was modified.
336For junk level 2, junking is done on allocation as well and without size
337restrictions.
338If the junk level is zero, no junking is performed.
339.It Cm R
340.Dq realloc .
341Always reallocate when
342.Fn realloc
343is called, even if the initial allocation was big enough.
344.\".Pp
345.\".It Cm U
346.\".Dq utrace .
347.\"Generate entries for
348.\".Xr ktrace 1
349.\"for all operations.
350.\"Consult the source for this one.
351.It Cm S
352.\" Malloc option S is vaguely documented on purpose.
353Enable all options suitable for security auditing.
354.It Cm U
355.Dq Free unmap .
356Enable use after free protection for larger allocations.
357Unused pages on the freelist are read and write protected to
358cause a segmentation fault upon access.
359.It Cm V
360.Dq Verbose .
361Use with
362.Cm D
363to get a verbose dump of malloc's internal state.
364.It Cm X
365.Dq xmalloc .
366Rather than return failure,
367.Xr abort 3
368the program with a diagnostic message on stderr.
369It is the intention that this option be set at compile time by
370including in the source:
371.Bd -literal -offset indent
372extern char *malloc_options;
373malloc_options = "X";
374.Ed
375.Pp
376Note that this will cause code that is supposed to handle
377out-of-memory conditions gracefully to abort instead.
378.It Cm <
379.Dq Halve the cache size .
380Decrease the size of the free page cache by a factor of two.
381.It Cm >
382.Dq Double the cache size .
383Increase the size of the free page cache by a factor of two.
384.El
385.Pp
386If a program changes behavior if any of these options (except
387.Cm X )
388are used,
389it is buggy.
390.Pp
391The default size of the cache is 64 single page allocations.
392It also caches a number of larger regions.
393Multi-threaded programs use multiple pools.
394.Sh RETURN VALUES
395Upon successful completion, the allocation functions
396return a pointer to the allocated space; otherwise,
397.Dv NULL
398is returned and
399.Va errno
400is set to
401.Er ENOMEM .
402The function
403.Fn aligned_alloc
404returns
405.Dv NULL
406and sets
407.Va errno
408to
409.Er EINVAL
410if
411.Fa alignment
412is not a power of 2.
413.Pp
414If
415.Fa nmemb
416or
417.Fa size
418is equal to 0, a unique pointer to an access protected,
419zero sized object is returned.
420Access via this pointer will generate a
421.Dv SIGSEGV
422exception.
423.Pp
424If multiplying
425.Fa nmemb
426and
427.Fa size
428results in integer overflow,
429.Fn calloc ,
430.Fn reallocarray
431and
432.Fn recallocarray
433return
434.Dv NULL
435and set
436.Va errno
437to
438.Er ENOMEM .
439.Pp
440If
441.Fa ptr
442is not
443.Dv NULL
444and multiplying
445.Fa oldnmemb
446and
447.Fa size
448results in integer overflow,
449.Fn recallocarray
450returns
451.Dv NULL
452and sets
453.Va errno
454to
455.Er EINVAL .
456.Sh IDIOMS
457Consider
458.Fn calloc
459or the extensions
460.Fn reallocarray
461and
462.Fn recallocarray
463when there is multiplication in the
464.Fa size
465argument of
466.Fn malloc
467or
468.Fn realloc .
469For example, avoid this common idiom as it may lead to integer overflow:
470.Bd -literal -offset indent
471if ((p = malloc(num * size)) == NULL)
472 err(1, NULL);
473.Ed
474.Pp
475A drop-in replacement is the
476.Ox
477extension
478.Fn reallocarray :
479.Bd -literal -offset indent
480if ((p = reallocarray(NULL, num, size)) == NULL)
481 err(1, NULL);
482.Ed
483.Pp
484Alternatively,
485.Fn calloc
486may be used at the cost of initialization overhead.
487.Pp
488When using
489.Fn realloc ,
490be careful to avoid the following idiom:
491.Bd -literal -offset indent
492size += 50;
493if ((p = realloc(p, size)) == NULL)
494 return (NULL);
495.Ed
496.Pp
497Do not adjust the variable describing how much memory has been allocated
498until the allocation has been successful.
499This can cause aberrant program behavior if the incorrect size value is used.
500In most cases, the above sample will also result in a leak of memory.
501As stated earlier, a return value of
502.Dv NULL
503indicates that the old object still remains allocated.
504Better code looks like this:
505.Bd -literal -offset indent
506newsize = size + 50;
507if ((newp = realloc(p, newsize)) == NULL) {
508 free(p);
509 p = NULL;
510 size = 0;
511 return (NULL);
512}
513p = newp;
514size = newsize;
515.Ed
516.Pp
517As with
518.Fn malloc ,
519it is important to ensure the new size value will not overflow;
520i.e. avoid allocations like the following:
521.Bd -literal -offset indent
522if ((newp = realloc(p, num * size)) == NULL) {
523 ...
524.Ed
525.Pp
526Instead, use
527.Fn reallocarray :
528.Bd -literal -offset indent
529if ((newp = reallocarray(p, num, size)) == NULL) {
530 ...
531.Ed
532.Pp
533Calling
534.Fn realloc
535with a
536.Dv NULL
537.Fa ptr
538is equivalent to calling
539.Fn malloc .
540Instead of this idiom:
541.Bd -literal -offset indent
542if (p == NULL)
543 newp = malloc(newsize);
544else
545 newp = realloc(p, newsize);
546.Ed
547.Pp
548Use the following:
549.Bd -literal -offset indent
550newp = realloc(p, newsize);
551.Ed
552.Pp
553The
554.Fn recallocarray
555function should be used for resizing objects containing sensitive data like
556keys.
557To avoid leaking information,
558it guarantees memory is cleared before placing it on the internal free list.
559Deallocation of such an object should be done by calling
560.Fn freezero .
561.Sh ENVIRONMENT
562.Bl -tag -width "MALLOC_OPTIONS"
563.It Ev MALLOC_OPTIONS
564String of option flags.
565.El
566.Sh EXAMPLES
567If
568.Fn malloc
569must be used with multiplication, be sure to test for overflow:
570.Bd -literal -offset indent
571size_t num, size;
572\&...
573
574/* Check for size_t overflow */
575if (size && num > SIZE_MAX / size)
576 errc(1, EOVERFLOW, "overflow");
577
578if ((p = malloc(num * size)) == NULL)
579 err(1, NULL);
580.Ed
581.Pp
582The above test is not sufficient in all cases.
583For example, multiplying ints requires a different set of checks:
584.Bd -literal -offset indent
585int num, size;
586\&...
587
588/* Avoid invalid requests */
589if (size < 0 || num < 0)
590 errc(1, EOVERFLOW, "overflow");
591
592/* Check for signed int overflow */
593if (size && num > INT_MAX / size)
594 errc(1, EOVERFLOW, "overflow");
595
596if ((p = malloc(num * size)) == NULL)
597 err(1, NULL);
598.Ed
599.Pp
600Assuming the implementation checks for integer overflow as
601.Ox
602does, it is much easier to use
603.Fn calloc ,
604.Fn reallocarray ,
605or
606.Fn recallocarray .
607.Pp
608The above examples could be simplified to:
609.Bd -literal -offset indent
610if ((p = reallocarray(NULL, num, size)) == NULL)
611 err(1, NULL);
612.Ed
613.Pp
614or at the cost of initialization:
615.Bd -literal -offset indent
616if ((p = calloc(num, size)) == NULL)
617 err(1, NULL);
618.Ed
619.Pp
620Set a systemwide reduction of the cache to a quarter of the
621default size and use guard pages:
622.Pp
623.Dl # sysctl vm.malloc_conf='G<<'
624.Sh DIAGNOSTICS
625If any of the functions detect an error condition,
626a message will be printed to file descriptor
6272 (not using stdio).
628Errors will result in the process being aborted.
629.Pp
630Here is a brief description of the error messages and what they mean:
631.Bl -tag -width Ds
632.It Dq out of memory
633If the
634.Cm X
635option is specified, it is an error for the allocation functions
636to return
637.Dv NULL .
638.It Dq bogus pointer (double free?)
639An attempt to
640.Fn free
641or
642reallocate an unallocated pointer was made.
643.It Dq double free
644There was an attempt to free an allocation that had already been freed.
645.It Dq write to free mem Va address Ns [ Va start Ns .. Ns Va end Ns ]@ Ns Va size
646An allocation has been modified after it was freed,
647or a chunk that was never allocated was written to.
648The
649.Va range
650at which corruption was detected is printed between [ and ].
651.Pp
652Enabling option
653.Cm D
654allows malloc to print information about where the allocation
655was done.
656.It Dq modified chunk-pointer
657The pointer passed to
658.Fn free
659or a reallocation function has been modified.
660.It Dq canary corrupted Va address Ns [ Va offset Ns ]@ Ns Va length Ns / Ns Va size
661A byte after the requested
662.Va length
663has been overwritten,
664indicating a heap overflow.
665The
666.Va offset
667at which corruption was detected is printed between [ and ],
668the requested
669.Va length
670of the allocation is printed before the / and the
671.Va size
672of the allocation after the /.
673.It Dq recorded size Va oldsize No inconsistent with Va size
674.Fn recallocarray
675or
676.Fn freezero
677has detected that the given old size does not match the recorded size in its
678meta data.
679Enabling option
680.Cm C
681allows
682.Fn recallocarray
683to catch more of these cases.
684.It Dq recursive call
685An attempt was made to call recursively into these functions, i.e., from a
686signal handler.
687This behavior is not supported.
688In particular, signal handlers should
689.Em not
690use any of the
691.Fn malloc
692functions nor utilize any other functions which may call
693.Fn malloc
694(e.g.,
695.Xr stdio 3
696routines).
697.It Dq unknown char in Ev MALLOC_OPTIONS
698We found something we didn't understand.
699.It any other error
700.Fn malloc
701detected an internal error;
702consult sources and/or wizards.
703.El
704.Sh SEE ALSO
705.Xr brk 2 ,
706.Xr mmap 2 ,
707.Xr munmap 2 ,
708.Xr sysctl 2 ,
709.Xr alloca 3 ,
710.Xr getpagesize 3 ,
711.Xr posix_memalign 3
712.Sh STANDARDS
713The
714.Fn malloc ,
715.Fn calloc ,
716.Fn realloc ,
717and
718.Fn free
719functions conform to
720.St -ansiC .
721The
722.Fn aligned_alloc
723function conforms to
724.St -isoC-2011 .
725The
726.Fn reallocarray
727function conforms to
728.St -p1003.1-2024 .
729.Pp
730If
731.Fa nmemb
732or
733.Fa size
734are 0, the return value is implementation defined;
735other conforming implementations may return
736.Dv NULL
737in this case.
738.Pp
739The
740.Ev MALLOC_OPTIONS
741environment variable, the
742.Va vm.malloc_conf
743sysctl and the
744.Sx DIAGNOSTICS
745output are extensions to the standard.
746.Sh HISTORY
747A
748.Fn free
749internal kernel function and a predecessor to
750.Fn malloc ,
751.Fn alloc ,
752first appeared in
753.At v1 .
754C library functions
755.Fn alloc
756and
757.Fn free
758appeared in
759.At v6 .
760The functions
761.Fn malloc ,
762.Fn calloc ,
763and
764.Fn realloc
765first appeared in
766.At v7 .
767.Pp
768A new implementation by Chris Kingsley was introduced in
769.Bx 4.2 ,
770followed by a complete rewrite by Poul-Henning Kamp which appeared in
771.Fx 2.2
772and was included in
773.Ox 2.0 .
774These implementations were all
775.Xr sbrk 2
776based.
777In
778.Ox 3.8 ,
779Thierry Deval rewrote
780.Nm
781to use the
782.Xr mmap 2
783system call,
784making the page addresses returned by
785.Nm
786random.
787A rewrite by Otto Moerbeek introducing a new central data structure and more
788randomization appeared in
789.Ox 4.4 .
790.Pp
791The
792.Fn reallocarray
793function appeared in
794.Ox 5.6 .
795The
796.Fn recallocarray
797function appeared in
798.Ox 6.1 .
799The
800.Fn freezero
801function appeared in
802.Ox 6.2 .
803The
804.Fn aligned_alloc
805function appeared in
806.Ox 6.5 .
807The
808.Fn malloc_conceal
809and
810.Fn calloc_conceal
811functions appeared in
812.Ox 6.6 .
813.Sh CAVEATS
814When using
815.Fn malloc ,
816be wary of signed integer and
817.Vt size_t
818overflow especially when there is multiplication in the
819.Fa size
820argument.
821.Pp
822Signed integer overflow will cause undefined behavior which compilers
823typically handle by wrapping back around to negative numbers.
824Depending on the input, this can result in allocating more or less
825memory than intended.
826.Pp
827An unsigned overflow has defined behavior which will wrap back around and
828return less memory than intended.
829.Pp
830A signed or unsigned integer overflow is a
831.Em security
832risk if less memory is returned than intended.
833Subsequent code may corrupt the heap by writing beyond the memory that was
834allocated.
835An attacker may be able to leverage this heap corruption to execute arbitrary
836code.
837.Pp
838Consider using
839.Fn calloc ,
840.Fn reallocarray
841or
842.Fn recallocarray
843instead of using multiplication in
844.Fn malloc
845and
846.Fn realloc
847to avoid these problems on
848.Ox .
849.Pp
850The mechanism to record caller functions when using malloc options
851.Cm 2 ,
852.Cm 3 ,
853or
854.Cm 4
855is not guaranteed to work for all platforms, compilers or compilation
856options,
857and might even crash your program.
858Use
859.Em only
860for debugging purposes.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
deleted file mode 100644
index cad8e5d6a1..0000000000
--- a/src/lib/libc/stdlib/malloc.c
+++ /dev/null
@@ -1,2781 +0,0 @@
1/* $OpenBSD: malloc.c,v 1.297 2024/09/20 02:00:46 jsg Exp $ */
2/*
3 * Copyright (c) 2008, 2010, 2011, 2016, 2023 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#ifndef MALLOC_SMALL
27#define MALLOC_STATS
28#endif
29
30#include <sys/types.h>
31#include <sys/queue.h>
32#include <sys/mman.h>
33#include <sys/sysctl.h>
34#include <uvm/uvmexp.h>
35#include <errno.h>
36#include <stdarg.h>
37#include <stdint.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#ifdef MALLOC_STATS
44#include <sys/tree.h>
45#include <sys/ktrace.h>
46#include <dlfcn.h>
47#endif
48
49#include "thread_private.h"
50#include <tib.h>
51
52#define MALLOC_PAGESHIFT _MAX_PAGE_SHIFT
53
54#define MALLOC_MINSHIFT 4
55#define MALLOC_MAXSHIFT (MALLOC_PAGESHIFT - 1)
56#define MALLOC_PAGESIZE (1UL << MALLOC_PAGESHIFT)
57#define MALLOC_MINSIZE (1UL << MALLOC_MINSHIFT)
58#define MALLOC_PAGEMASK (MALLOC_PAGESIZE - 1)
59#define MASK_POINTER(p) ((void *)(((uintptr_t)(p)) & ~MALLOC_PAGEMASK))
60
61#define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT)
62#define MALLOC_MAXCACHE 256
63#define MALLOC_DELAYED_CHUNK_MASK 15
64#ifdef MALLOC_STATS
65#define MALLOC_INITIAL_REGIONS 512
66#else
67#define MALLOC_INITIAL_REGIONS (MALLOC_PAGESIZE / sizeof(struct region_info))
68#endif
69#define MALLOC_DEFAULT_CACHE 64
70#define MALLOC_CHUNK_LISTS 4
71#define CHUNK_CHECK_LENGTH 32
72
73#define B2SIZE(b) ((b) * MALLOC_MINSIZE)
74#define B2ALLOC(b) ((b) == 0 ? MALLOC_MINSIZE : \
75 (b) * MALLOC_MINSIZE)
76#define BUCKETS (MALLOC_MAXCHUNK / MALLOC_MINSIZE)
77
78/*
79 * We move allocations between half a page and a whole page towards the end,
80 * subject to alignment constraints. This is the extra headroom we allow.
81 * Set to zero to be the most strict.
82 */
83#define MALLOC_LEEWAY 0
84#define MALLOC_MOVE_COND(sz) ((sz) - mopts.malloc_guard < \
85 MALLOC_PAGESIZE - MALLOC_LEEWAY)
86#define MALLOC_MOVE(p, sz) (((char *)(p)) + \
87 ((MALLOC_PAGESIZE - MALLOC_LEEWAY - \
88 ((sz) - mopts.malloc_guard)) & \
89 ~(MALLOC_MINSIZE - 1)))
90
91#define PAGEROUND(x) (((x) + (MALLOC_PAGEMASK)) & ~MALLOC_PAGEMASK)
92
93/*
94 * What to use for Junk. This is the byte value we use to fill with
95 * when the 'J' option is enabled. Use SOME_JUNK right after alloc,
96 * and SOME_FREEJUNK right before free.
97 */
98#define SOME_JUNK 0xdb /* deadbeef */
99#define SOME_FREEJUNK 0xdf /* dead, free */
100#define SOME_FREEJUNK_ULL 0xdfdfdfdfdfdfdfdfULL
101
102#define MMAP(sz,f) mmap(NULL, (sz), PROT_READ | PROT_WRITE, \
103 MAP_ANON | MAP_PRIVATE | (f), -1, 0)
104
105#define MMAPNONE(sz,f) mmap(NULL, (sz), PROT_NONE, \
106 MAP_ANON | MAP_PRIVATE | (f), -1, 0)
107
108#define MMAPA(a,sz,f) mmap((a), (sz), PROT_READ | PROT_WRITE, \
109 MAP_ANON | MAP_PRIVATE | (f), -1, 0)
110
111struct region_info {
112 void *p; /* page; low bits used to mark chunks */
113 uintptr_t size; /* size for pages, or chunk_info pointer */
114#ifdef MALLOC_STATS
115 void **f; /* where allocated from */
116#endif
117};
118
119LIST_HEAD(chunk_head, chunk_info);
120
121/*
122 * Two caches, one for "small" regions, one for "big".
123 * Small cache is an array per size, big cache is one array with different
124 * sized regions
125 */
126#define MAX_SMALLCACHEABLE_SIZE 32
127#define MAX_BIGCACHEABLE_SIZE 512
128/* If the total # of pages is larger than this, evict before inserting */
129#define BIGCACHE_FILL(sz) (MAX_BIGCACHEABLE_SIZE * (sz) / 4)
130
131struct smallcache {
132 void **pages;
133 ushort length;
134 ushort max;
135};
136
137struct bigcache {
138 void *page;
139 size_t psize;
140};
141
142#ifdef MALLOC_STATS
143#define NUM_FRAMES 4
144struct btnode {
145 RBT_ENTRY(btnode) entry;
146 void *caller[NUM_FRAMES];
147};
148RBT_HEAD(btshead, btnode);
149RBT_PROTOTYPE(btshead, btnode, entry, btcmp);
150#endif /* MALLOC_STATS */
151
152struct dir_info {
153 u_int32_t canary1;
154 int active; /* status of malloc */
155 struct region_info *r; /* region slots */
156 size_t regions_total; /* number of region slots */
157 size_t regions_free; /* number of free slots */
158 size_t rbytesused; /* random bytes used */
159 const char *func; /* current function */
160 int malloc_junk; /* junk fill? */
161 int mmap_flag; /* extra flag for mmap */
162 int mutex;
163 int malloc_mt; /* multi-threaded mode? */
164 /* lists of free chunk info structs */
165 struct chunk_head chunk_info_list[BUCKETS + 1];
166 /* lists of chunks with free slots */
167 struct chunk_head chunk_dir[BUCKETS + 1][MALLOC_CHUNK_LISTS];
168 /* delayed free chunk slots */
169 void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1];
170 u_char rbytes[32]; /* random bytes */
171 /* free pages cache */
172 struct smallcache smallcache[MAX_SMALLCACHEABLE_SIZE];
173 size_t bigcache_used;
174 size_t bigcache_size;
175 struct bigcache *bigcache;
176 void *chunk_pages;
177 size_t chunk_pages_used;
178#ifdef MALLOC_STATS
179 void *caller;
180 size_t inserts;
181 size_t insert_collisions;
182 size_t deletes;
183 size_t delete_moves;
184 size_t cheap_realloc_tries;
185 size_t cheap_reallocs;
186 size_t malloc_used; /* bytes allocated */
187 size_t malloc_guarded; /* bytes used for guards */
188 struct btshead btraces; /* backtraces seen */
189 struct btnode *btnodes; /* store of backtrace nodes */
190 size_t btnodesused;
191#define STATS_ADD(x,y) ((x) += (y))
192#define STATS_SUB(x,y) ((x) -= (y))
193#define STATS_INC(x) ((x)++)
194#define STATS_ZERO(x) ((x) = 0)
195#define STATS_SETF(x,y) ((x)->f = (y))
196#define STATS_SETFN(x,k,y) ((x)->f[k] = (y))
197#define SET_CALLER(x,y) if (DO_STATS) ((x)->caller = (y))
198#else
199#define STATS_ADD(x,y) /* nothing */
200#define STATS_SUB(x,y) /* nothing */
201#define STATS_INC(x) /* nothing */
202#define STATS_ZERO(x) /* nothing */
203#define STATS_SETF(x,y) /* nothing */
204#define STATS_SETFN(x,k,y) /* nothing */
205#define SET_CALLER(x,y) /* nothing */
206#endif /* MALLOC_STATS */
207 u_int32_t canary2;
208};
209
210static void unmap(struct dir_info *d, void *p, size_t sz, size_t clear);
211
212/*
213 * This structure describes a page worth of chunks.
214 *
215 * How many bits per u_short in the bitmap
216 */
217#define MALLOC_BITS (NBBY * sizeof(u_short))
218struct chunk_info {
219 LIST_ENTRY(chunk_info) entries;
220 void *page; /* pointer to the page */
221 /* number of shorts should add up to 8, check alloc_chunk_info() */
222 u_short canary;
223 u_short bucket;
224 u_short free; /* how many free chunks */
225 u_short total; /* how many chunks */
226 u_short offset; /* requested size table offset */
227#define CHUNK_INFO_TAIL 3
228 u_short bits[CHUNK_INFO_TAIL]; /* which chunks are free */
229};
230
231#define CHUNK_FREE(i, n) ((i)->bits[(n) / MALLOC_BITS] & \
232 (1U << ((n) % MALLOC_BITS)))
233
234struct malloc_readonly {
235 /* Main bookkeeping information */
236 struct dir_info *malloc_pool[_MALLOC_MUTEXES];
237 u_int malloc_mutexes; /* how much in actual use? */
238 int malloc_freecheck; /* Extensive double free check */
239 int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
240 int def_malloc_junk; /* junk fill? */
241 int malloc_realloc; /* always realloc? */
242 int malloc_xmalloc; /* xmalloc behaviour? */
243 u_int chunk_canaries; /* use canaries after chunks? */
244 int internal_funcs; /* use better recallocarray/freezero? */
245 u_int def_maxcache; /* free pages we cache */
246 u_int junk_loc; /* variation in location of junk */
247 size_t malloc_guard; /* use guard pages after allocations? */
248#ifdef MALLOC_STATS
249 int malloc_stats; /* save callers, dump leak report */
250 int malloc_verbose; /* dump verbose statistics at end */
251#define DO_STATS mopts.malloc_stats
252#else
253#define DO_STATS 0
254#endif
255 u_int32_t malloc_canary; /* Matched against ones in pool */
256};
257
258
259/* This object is mapped PROT_READ after initialisation to prevent tampering */
260static union {
261 struct malloc_readonly mopts;
262 u_char _pad[MALLOC_PAGESIZE];
263} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)))
264 __attribute__((section(".openbsd.mutable")));
265#define mopts malloc_readonly.mopts
266
267char *malloc_options; /* compile-time options */
268
269static __dead void wrterror(struct dir_info *d, char *msg, ...)
270 __attribute__((__format__ (printf, 2, 3)));
271
272#ifdef MALLOC_STATS
273void malloc_dump(void);
274PROTO_NORMAL(malloc_dump);
275static void malloc_exit(void);
276static void print_chunk_details(struct dir_info *, void *, size_t, size_t);
277static void* store_caller(struct dir_info *, struct btnode *);
278
279/* below are the arches for which deeper caller info has been tested */
280#if defined(__aarch64__) || \
281 defined(__amd64__) || \
282 defined(__arm__) || \
283 defined(__i386__) || \
284 defined(__powerpc__)
285__attribute__((always_inline))
286static inline void*
287caller(struct dir_info *d)
288{
289 struct btnode p;
290 int level = DO_STATS;
291
292 if (level == 0)
293 return NULL;
294
295 memset(&p.caller, 0, sizeof(p.caller));
296 if (level >= 1)
297 p.caller[0] = __builtin_extract_return_addr(
298 __builtin_return_address(0));
299 if (p.caller[0] != NULL && level >= 2)
300 p.caller[1] = __builtin_extract_return_addr(
301 __builtin_return_address(1));
302 if (p.caller[1] != NULL && level >= 3)
303 p.caller[2] = __builtin_extract_return_addr(
304 __builtin_return_address(2));
305 if (p.caller[2] != NULL && level >= 4)
306 p.caller[3] = __builtin_extract_return_addr(
307 __builtin_return_address(3));
308 return store_caller(d, &p);
309}
310#else
311__attribute__((always_inline))
312static inline void* caller(struct dir_info *d)
313{
314 struct btnode p;
315
316 if (DO_STATS == 0)
317 return NULL;
318 memset(&p.caller, 0, sizeof(p.caller));
319 p.caller[0] = __builtin_extract_return_addr(__builtin_return_address(0));
320 return store_caller(d, &p);
321}
322#endif
323#endif /* MALLOC_STATS */
324
325/* low bits of r->p determine size: 0 means >= page size and r->size holding
326 * real size, otherwise low bits is the bucket + 1
327 */
328#define REALSIZE(sz, r) \
329 (sz) = (uintptr_t)(r)->p & MALLOC_PAGEMASK, \
330 (sz) = ((sz) == 0 ? (r)->size : B2SIZE((sz) - 1))
331
332static inline size_t
333hash(void *p)
334{
335 size_t sum;
336 uintptr_t u;
337
338 u = (uintptr_t)p >> MALLOC_PAGESHIFT;
339 sum = u;
340 sum = (sum << 7) - sum + (u >> 16);
341#ifdef __LP64__
342 sum = (sum << 7) - sum + (u >> 32);
343 sum = (sum << 7) - sum + (u >> 48);
344#endif
345 return sum;
346}
347
348static inline struct dir_info *
349getpool(void)
350{
351 if (mopts.malloc_pool[1] == NULL || !mopts.malloc_pool[1]->malloc_mt)
352 return mopts.malloc_pool[1];
353 else /* first one reserved for special pool */
354 return mopts.malloc_pool[1 + TIB_GET()->tib_tid %
355 (mopts.malloc_mutexes - 1)];
356}
357
358static __dead void
359wrterror(struct dir_info *d, char *msg, ...)
360{
361 int saved_errno = errno;
362 va_list ap;
363
364 dprintf(STDERR_FILENO, "%s(%d) in %s(): ", __progname,
365 getpid(), (d != NULL && d->func) ? d->func : "unknown");
366 va_start(ap, msg);
367 vdprintf(STDERR_FILENO, msg, ap);
368 va_end(ap);
369 dprintf(STDERR_FILENO, "\n");
370
371#ifdef MALLOC_STATS
372 if (DO_STATS && mopts.malloc_verbose)
373 malloc_dump();
374#endif
375
376 errno = saved_errno;
377
378 abort();
379}
380
381static void
382rbytes_init(struct dir_info *d)
383{
384 arc4random_buf(d->rbytes, sizeof(d->rbytes));
385 /* add 1 to account for using d->rbytes[0] */
386 d->rbytesused = 1 + d->rbytes[0] % (sizeof(d->rbytes) / 2);
387}
388
389static inline u_char
390getrbyte(struct dir_info *d)
391{
392 u_char x;
393
394 if (d->rbytesused >= sizeof(d->rbytes))
395 rbytes_init(d);
396 x = d->rbytes[d->rbytesused++];
397 return x;
398}
399
400static void
401omalloc_parseopt(char opt)
402{
403 switch (opt) {
404 case '+':
405 mopts.malloc_mutexes <<= 1;
406 if (mopts.malloc_mutexes > _MALLOC_MUTEXES)
407 mopts.malloc_mutexes = _MALLOC_MUTEXES;
408 break;
409 case '-':
410 mopts.malloc_mutexes >>= 1;
411 if (mopts.malloc_mutexes < 2)
412 mopts.malloc_mutexes = 2;
413 break;
414 case '>':
415 mopts.def_maxcache <<= 1;
416 if (mopts.def_maxcache > MALLOC_MAXCACHE)
417 mopts.def_maxcache = MALLOC_MAXCACHE;
418 break;
419 case '<':
420 mopts.def_maxcache >>= 1;
421 break;
422 case 'c':
423 mopts.chunk_canaries = 0;
424 break;
425 case 'C':
426 mopts.chunk_canaries = 1;
427 break;
428#ifdef MALLOC_STATS
429 case 'd':
430 mopts.malloc_stats = 0;
431 break;
432 case 'D':
433 case '1':
434 mopts.malloc_stats = 1;
435 break;
436 case '2':
437 mopts.malloc_stats = 2;
438 break;
439 case '3':
440 mopts.malloc_stats = 3;
441 break;
442 case '4':
443 mopts.malloc_stats = 4;
444 break;
445#endif /* MALLOC_STATS */
446 case 'f':
447 mopts.malloc_freecheck = 0;
448 mopts.malloc_freeunmap = 0;
449 break;
450 case 'F':
451 mopts.malloc_freecheck = 1;
452 mopts.malloc_freeunmap = 1;
453 break;
454 case 'g':
455 mopts.malloc_guard = 0;
456 break;
457 case 'G':
458 mopts.malloc_guard = MALLOC_PAGESIZE;
459 break;
460 case 'j':
461 if (mopts.def_malloc_junk > 0)
462 mopts.def_malloc_junk--;
463 break;
464 case 'J':
465 if (mopts.def_malloc_junk < 2)
466 mopts.def_malloc_junk++;
467 break;
468 case 'r':
469 mopts.malloc_realloc = 0;
470 break;
471 case 'R':
472 mopts.malloc_realloc = 1;
473 break;
474 case 'u':
475 mopts.malloc_freeunmap = 0;
476 break;
477 case 'U':
478 mopts.malloc_freeunmap = 1;
479 break;
480#ifdef MALLOC_STATS
481 case 'v':
482 mopts.malloc_verbose = 0;
483 break;
484 case 'V':
485 mopts.malloc_verbose = 1;
486 break;
487#endif /* MALLOC_STATS */
488 case 'x':
489 mopts.malloc_xmalloc = 0;
490 break;
491 case 'X':
492 mopts.malloc_xmalloc = 1;
493 break;
494 default:
495 dprintf(STDERR_FILENO, "malloc() warning: "
496 "unknown char in MALLOC_OPTIONS\n");
497 break;
498 }
499}
500
501static void
502omalloc_init(void)
503{
504 char *p, *q, b[16];
505 int i, j;
506 const int mib[2] = { CTL_VM, VM_MALLOC_CONF };
507 size_t sb;
508
509 /*
510 * Default options
511 */
512 mopts.malloc_mutexes = 8;
513 mopts.def_malloc_junk = 1;
514 mopts.def_maxcache = MALLOC_DEFAULT_CACHE;
515
516 for (i = 0; i < 3; i++) {
517 switch (i) {
518 case 0:
519 sb = sizeof(b);
520 j = sysctl(mib, 2, b, &sb, NULL, 0);
521 if (j != 0)
522 continue;
523 p = b;
524 break;
525 case 1:
526 if (issetugid() == 0)
527 p = getenv("MALLOC_OPTIONS");
528 else
529 continue;
530 break;
531 case 2:
532 p = malloc_options;
533 break;
534 default:
535 p = NULL;
536 }
537
538 for (; p != NULL && *p != '\0'; p++) {
539 switch (*p) {
540 case 'S':
541 for (q = "CFGJ"; *q != '\0'; q++)
542 omalloc_parseopt(*q);
543 mopts.def_maxcache = 0;
544 break;
545 case 's':
546 for (q = "cfgj"; *q != '\0'; q++)
547 omalloc_parseopt(*q);
548 mopts.def_maxcache = MALLOC_DEFAULT_CACHE;
549 break;
550 default:
551 omalloc_parseopt(*p);
552 break;
553 }
554 }
555 }
556
557#ifdef MALLOC_STATS
558 if (DO_STATS && (atexit(malloc_exit) == -1)) {
559 dprintf(STDERR_FILENO, "malloc() warning: atexit(3) failed."
560 " Will not be able to dump stats on exit\n");
561 }
562#endif
563
564 while ((mopts.malloc_canary = arc4random()) == 0)
565 ;
566 mopts.junk_loc = arc4random();
567 if (mopts.chunk_canaries)
568 do {
569 mopts.chunk_canaries = arc4random();
570 } while ((u_char)mopts.chunk_canaries == 0 ||
571 (u_char)mopts.chunk_canaries == SOME_FREEJUNK);
572}
573
574static void
575omalloc_poolinit(struct dir_info *d, int mmap_flag)
576{
577 u_int i, j;
578
579 d->r = NULL;
580 d->rbytesused = sizeof(d->rbytes);
581 d->regions_free = d->regions_total = 0;
582 for (i = 0; i <= BUCKETS; i++) {
583 LIST_INIT(&d->chunk_info_list[i]);
584 for (j = 0; j < MALLOC_CHUNK_LISTS; j++)
585 LIST_INIT(&d->chunk_dir[i][j]);
586 }
587 d->mmap_flag = mmap_flag;
588 d->malloc_junk = mopts.def_malloc_junk;
589#ifdef MALLOC_STATS
590 RBT_INIT(btshead, &d->btraces);
591#endif
592 d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
593 d->canary2 = ~d->canary1;
594}
595
596static int
597omalloc_grow(struct dir_info *d)
598{
599 size_t newtotal;
600 size_t newsize;
601 size_t mask;
602 size_t i, oldpsz;
603 struct region_info *p;
604
605 if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2)
606 return 1;
607
608 newtotal = d->regions_total == 0 ? MALLOC_INITIAL_REGIONS :
609 d->regions_total * 2;
610 newsize = PAGEROUND(newtotal * sizeof(struct region_info));
611 mask = newtotal - 1;
612
613 /* Don't use cache here, we don't want user uaf touch this */
614 p = MMAP(newsize, d->mmap_flag);
615 if (p == MAP_FAILED)
616 return 1;
617
618 STATS_ADD(d->malloc_used, newsize);
619 STATS_ZERO(d->inserts);
620 STATS_ZERO(d->insert_collisions);
621 for (i = 0; i < d->regions_total; i++) {
622 void *q = d->r[i].p;
623 if (q != NULL) {
624 size_t index = hash(q) & mask;
625 STATS_INC(d->inserts);
626 while (p[index].p != NULL) {
627 index = (index - 1) & mask;
628 STATS_INC(d->insert_collisions);
629 }
630 p[index] = d->r[i];
631 }
632 }
633
634 if (d->regions_total > 0) {
635 oldpsz = PAGEROUND(d->regions_total *
636 sizeof(struct region_info));
637 /* clear to avoid meta info ending up in the cache */
638 unmap(d, d->r, oldpsz, oldpsz);
639 }
640 d->regions_free += newtotal - d->regions_total;
641 d->regions_total = newtotal;
642 d->r = p;
643 return 0;
644}
645
646/*
647 * The hashtable uses the assumption that p is never NULL. This holds since
648 * non-MAP_FIXED mappings with hint 0 start at BRKSIZ.
649 */
650static int
651insert(struct dir_info *d, void *p, size_t sz, void *f)
652{
653 size_t index;
654 size_t mask;
655 void *q;
656
657 if (d->regions_free * 4 < d->regions_total || d->regions_total == 0) {
658 if (omalloc_grow(d))
659 return 1;
660 }
661 mask = d->regions_total - 1;
662 index = hash(p) & mask;
663 q = d->r[index].p;
664 STATS_INC(d->inserts);
665 while (q != NULL) {
666 index = (index - 1) & mask;
667 q = d->r[index].p;
668 STATS_INC(d->insert_collisions);
669 }
670 d->r[index].p = p;
671 d->r[index].size = sz;
672 STATS_SETF(&d->r[index], f);
673 d->regions_free--;
674 return 0;
675}
676
677static struct region_info *
678find(struct dir_info *d, void *p)
679{
680 size_t index;
681 size_t mask = d->regions_total - 1;
682 void *q, *r;
683
684 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
685 d->canary1 != ~d->canary2)
686 wrterror(d, "internal struct corrupt");
687 if (d->r == NULL)
688 return NULL;
689 p = MASK_POINTER(p);
690 index = hash(p) & mask;
691 r = d->r[index].p;
692 q = MASK_POINTER(r);
693 while (q != p && r != NULL) {
694 index = (index - 1) & mask;
695 r = d->r[index].p;
696 q = MASK_POINTER(r);
697 }
698 return (q == p && r != NULL) ? &d->r[index] : NULL;
699}
700
701static void
702delete(struct dir_info *d, struct region_info *ri)
703{
704 /* algorithm R, Knuth Vol III section 6.4 */
705 size_t mask = d->regions_total - 1;
706 size_t i, j, r;
707
708 if (d->regions_total & (d->regions_total - 1))
709 wrterror(d, "regions_total not 2^x");
710 d->regions_free++;
711 STATS_INC(d->deletes);
712
713 i = ri - d->r;
714 for (;;) {
715 d->r[i].p = NULL;
716 d->r[i].size = 0;
717 j = i;
718 for (;;) {
719 i = (i - 1) & mask;
720 if (d->r[i].p == NULL)
721 return;
722 r = hash(d->r[i].p) & mask;
723 if ((i <= r && r < j) || (r < j && j < i) ||
724 (j < i && i <= r))
725 continue;
726 d->r[j] = d->r[i];
727 STATS_INC(d->delete_moves);
728 break;
729 }
730
731 }
732}
733
734static inline void
735junk_free(int junk, void *p, size_t sz)
736{
737 size_t i, step = 1;
738 uint64_t *lp = p;
739
740 if (junk == 0 || sz == 0)
741 return;
742 sz /= sizeof(uint64_t);
743 if (junk == 1) {
744 if (sz > MALLOC_PAGESIZE / sizeof(uint64_t))
745 sz = MALLOC_PAGESIZE / sizeof(uint64_t);
746 step = sz / 4;
747 if (step == 0)
748 step = 1;
749 }
750 /* Do not always put the free junk bytes in the same spot.
751 There is modulo bias here, but we ignore that. */
752 for (i = mopts.junk_loc % step; i < sz; i += step)
753 lp[i] = SOME_FREEJUNK_ULL;
754}
755
756static inline void
757validate_junk(struct dir_info *pool, void *p, size_t argsz)
758{
759 size_t i, sz, step = 1;
760 uint64_t *lp = p;
761
762 if (pool->malloc_junk == 0 || argsz == 0)
763 return;
764 sz = argsz / sizeof(uint64_t);
765 if (pool->malloc_junk == 1) {
766 if (sz > MALLOC_PAGESIZE / sizeof(uint64_t))
767 sz = MALLOC_PAGESIZE / sizeof(uint64_t);
768 step = sz / 4;
769 if (step == 0)
770 step = 1;
771 }
772 /* see junk_free */
773 for (i = mopts.junk_loc % step; i < sz; i += step) {
774 if (lp[i] != SOME_FREEJUNK_ULL) {
775#ifdef MALLOC_STATS
776 if (DO_STATS && argsz <= MALLOC_MAXCHUNK)
777 print_chunk_details(pool, lp, argsz, i);
778 else
779#endif
780 wrterror(pool,
781 "write to free mem %p[%zu..%zu]@%zu",
782 lp, i * sizeof(uint64_t),
783 (i + 1) * sizeof(uint64_t) - 1, argsz);
784 }
785 }
786}
787
788
789/*
790 * Cache maintenance.
791 * Opposed to the regular region data structure, the sizes in the
792 * cache are in MALLOC_PAGESIZE units.
793 */
794static void
795unmap(struct dir_info *d, void *p, size_t sz, size_t clear)
796{
797 size_t psz = sz >> MALLOC_PAGESHIFT;
798 void *r;
799 u_short i;
800 struct smallcache *cache;
801
802 if (sz != PAGEROUND(sz) || psz == 0)
803 wrterror(d, "munmap round");
804
805 if (d->bigcache_size > 0 && psz > MAX_SMALLCACHEABLE_SIZE &&
806 psz <= MAX_BIGCACHEABLE_SIZE) {
807 u_short base = getrbyte(d);
808 u_short j;
809
810 /* don't look through all slots */
811 for (j = 0; j < d->bigcache_size / 4; j++) {
812 i = (base + j) & (d->bigcache_size - 1);
813 if (d->bigcache_used <
814 BIGCACHE_FILL(d->bigcache_size)) {
815 if (d->bigcache[i].psize == 0)
816 break;
817 } else {
818 if (d->bigcache[i].psize != 0)
819 break;
820 }
821 }
822 /* if we didn't find a preferred slot, use random one */
823 if (d->bigcache[i].psize != 0) {
824 size_t tmp;
825
826 r = d->bigcache[i].page;
827 d->bigcache_used -= d->bigcache[i].psize;
828 tmp = d->bigcache[i].psize << MALLOC_PAGESHIFT;
829 if (!mopts.malloc_freeunmap)
830 validate_junk(d, r, tmp);
831 if (munmap(r, tmp))
832 wrterror(d, "munmap %p", r);
833 STATS_SUB(d->malloc_used, tmp);
834 }
835
836 if (clear > 0)
837 explicit_bzero(p, clear);
838 if (mopts.malloc_freeunmap) {
839 if (mprotect(p, sz, PROT_NONE))
840 wrterror(d, "mprotect %p", r);
841 } else
842 junk_free(d->malloc_junk, p, sz);
843 d->bigcache[i].page = p;
844 d->bigcache[i].psize = psz;
845 d->bigcache_used += psz;
846 return;
847 }
848 if (psz > MAX_SMALLCACHEABLE_SIZE || d->smallcache[psz - 1].max == 0) {
849 if (munmap(p, sz))
850 wrterror(d, "munmap %p", p);
851 STATS_SUB(d->malloc_used, sz);
852 return;
853 }
854 cache = &d->smallcache[psz - 1];
855 if (cache->length == cache->max) {
856 int fresh;
857 /* use a random slot */
858 i = getrbyte(d) & (cache->max - 1);
859 r = cache->pages[i];
860 fresh = (uintptr_t)r & 1;
861 *(uintptr_t*)&r &= ~1UL;
862 if (!fresh && !mopts.malloc_freeunmap)
863 validate_junk(d, r, sz);
864 if (munmap(r, sz))
865 wrterror(d, "munmap %p", r);
866 STATS_SUB(d->malloc_used, sz);
867 cache->length--;
868 } else
869 i = cache->length;
870
871 /* fill slot */
872 if (clear > 0)
873 explicit_bzero(p, clear);
874 if (mopts.malloc_freeunmap)
875 mprotect(p, sz, PROT_NONE);
876 else
877 junk_free(d->malloc_junk, p, sz);
878 cache->pages[i] = p;
879 cache->length++;
880}
881
882static void *
883map(struct dir_info *d, size_t sz, int zero_fill)
884{
885 size_t psz = sz >> MALLOC_PAGESHIFT;
886 u_short i;
887 void *p;
888 struct smallcache *cache;
889
890 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
891 d->canary1 != ~d->canary2)
892 wrterror(d, "internal struct corrupt");
893 if (sz != PAGEROUND(sz) || psz == 0)
894 wrterror(d, "map round");
895
896
897 if (d->bigcache_size > 0 && psz > MAX_SMALLCACHEABLE_SIZE &&
898 psz <= MAX_BIGCACHEABLE_SIZE) {
899 size_t base = getrbyte(d);
900 size_t cached = d->bigcache_used;
901 ushort j;
902
903 for (j = 0; j < d->bigcache_size && cached >= psz; j++) {
904 i = (j + base) & (d->bigcache_size - 1);
905 if (d->bigcache[i].psize == psz) {
906 p = d->bigcache[i].page;
907 d->bigcache_used -= psz;
908 d->bigcache[i].page = NULL;
909 d->bigcache[i].psize = 0;
910
911 if (!mopts.malloc_freeunmap)
912 validate_junk(d, p, sz);
913 if (mopts.malloc_freeunmap)
914 mprotect(p, sz, PROT_READ | PROT_WRITE);
915 if (zero_fill)
916 memset(p, 0, sz);
917 else if (mopts.malloc_freeunmap)
918 junk_free(d->malloc_junk, p, sz);
919 return p;
920 }
921 cached -= d->bigcache[i].psize;
922 }
923 }
924 if (psz <= MAX_SMALLCACHEABLE_SIZE && d->smallcache[psz - 1].max > 0) {
925 cache = &d->smallcache[psz - 1];
926 if (cache->length > 0) {
927 int fresh;
928 if (cache->length == 1)
929 p = cache->pages[--cache->length];
930 else {
931 i = getrbyte(d) % cache->length;
932 p = cache->pages[i];
933 cache->pages[i] = cache->pages[--cache->length];
934 }
935 /* check if page was not junked, i.e. "fresh
936 we use the lsb of the pointer for that */
937 fresh = (uintptr_t)p & 1UL;
938 *(uintptr_t*)&p &= ~1UL;
939 if (!fresh && !mopts.malloc_freeunmap)
940 validate_junk(d, p, sz);
941 if (mopts.malloc_freeunmap)
942 mprotect(p, sz, PROT_READ | PROT_WRITE);
943 if (zero_fill)
944 memset(p, 0, sz);
945 else if (mopts.malloc_freeunmap)
946 junk_free(d->malloc_junk, p, sz);
947 return p;
948 }
949 if (psz <= 1) {
950 p = MMAP(cache->max * sz, d->mmap_flag);
951 if (p != MAP_FAILED) {
952 STATS_ADD(d->malloc_used, cache->max * sz);
953 cache->length = cache->max - 1;
954 for (i = 0; i < cache->max - 1; i++) {
955 void *q = (char*)p + i * sz;
956 cache->pages[i] = q;
957 /* mark pointer in slot as not junked */
958 *(uintptr_t*)&cache->pages[i] |= 1UL;
959 }
960 if (mopts.malloc_freeunmap)
961 mprotect(p, (cache->max - 1) * sz,
962 PROT_NONE);
963 p = (char*)p + (cache->max - 1) * sz;
964 /* zero fill not needed, freshly mmapped */
965 return p;
966 }
967 }
968
969 }
970 p = MMAP(sz, d->mmap_flag);
971 if (p != MAP_FAILED)
972 STATS_ADD(d->malloc_used, sz);
973 /* zero fill not needed */
974 return p;
975}
976
977static void
978init_chunk_info(struct dir_info *d, struct chunk_info *p, u_int bucket)
979{
980 u_int i;
981
982 p->bucket = bucket;
983 p->total = p->free = MALLOC_PAGESIZE / B2ALLOC(bucket);
984 p->offset = howmany(p->total, MALLOC_BITS);
985 p->canary = (u_short)d->canary1;
986
987 /* set all valid bits in the bitmap */
988 i = p->total - 1;
989 memset(p->bits, 0xff, sizeof(p->bits[0]) * (i / MALLOC_BITS));
990 p->bits[i / MALLOC_BITS] = (2U << (i % MALLOC_BITS)) - 1;
991}
992
993static struct chunk_info *
994alloc_chunk_info(struct dir_info *d, u_int bucket)
995{
996 struct chunk_info *p;
997
998 if (LIST_EMPTY(&d->chunk_info_list[bucket])) {
999 const size_t chunk_pages = 64;
1000 size_t size, count, i;
1001 char *q;
1002
1003 count = MALLOC_PAGESIZE / B2ALLOC(bucket);
1004
1005 size = howmany(count, MALLOC_BITS);
1006 /* see declaration of struct chunk_info */
1007 if (size <= CHUNK_INFO_TAIL)
1008 size = 0;
1009 else
1010 size -= CHUNK_INFO_TAIL;
1011 size = sizeof(struct chunk_info) + size * sizeof(u_short);
1012 if (mopts.chunk_canaries && bucket > 0)
1013 size += count * sizeof(u_short);
1014 size = _ALIGN(size);
1015 count = MALLOC_PAGESIZE / size;
1016
1017 /* Don't use cache here, we don't want user uaf touch this */
1018 if (d->chunk_pages_used == chunk_pages ||
1019 d->chunk_pages == NULL) {
1020 q = MMAP(MALLOC_PAGESIZE * chunk_pages, d->mmap_flag);
1021 if (q == MAP_FAILED)
1022 return NULL;
1023 d->chunk_pages = q;
1024 d->chunk_pages_used = 0;
1025 STATS_ADD(d->malloc_used, MALLOC_PAGESIZE *
1026 chunk_pages);
1027 }
1028 q = (char *)d->chunk_pages + d->chunk_pages_used *
1029 MALLOC_PAGESIZE;
1030 d->chunk_pages_used++;
1031
1032 for (i = 0; i < count; i++, q += size) {
1033 p = (struct chunk_info *)q;
1034 LIST_INSERT_HEAD(&d->chunk_info_list[bucket], p,
1035 entries);
1036 }
1037 }
1038 p = LIST_FIRST(&d->chunk_info_list[bucket]);
1039 LIST_REMOVE(p, entries);
1040 if (p->total == 0)
1041 init_chunk_info(d, p, bucket);
1042 return p;
1043}
1044
1045/*
1046 * Allocate a page of chunks
1047 */
1048static struct chunk_info *
1049omalloc_make_chunks(struct dir_info *d, u_int bucket, u_int listnum)
1050{
1051 struct chunk_info *bp;
1052 void *pp;
1053 void *ff = NULL;
1054
1055 /* Allocate a new bucket */
1056 pp = map(d, MALLOC_PAGESIZE, 0);
1057 if (pp == MAP_FAILED)
1058 return NULL;
1059 if (DO_STATS) {
1060 ff = map(d, MALLOC_PAGESIZE, 0);
1061 if (ff == MAP_FAILED)
1062 goto err;
1063 memset(ff, 0, sizeof(void *) * MALLOC_PAGESIZE /
1064 B2ALLOC(bucket));
1065 }
1066
1067 /* memory protect the page allocated in the malloc(0) case */
1068 if (bucket == 0 && mprotect(pp, MALLOC_PAGESIZE, PROT_NONE) == -1)
1069 goto err;
1070
1071 bp = alloc_chunk_info(d, bucket);
1072 if (bp == NULL)
1073 goto err;
1074 bp->page = pp;
1075
1076 if (insert(d, (void *)((uintptr_t)pp | (bucket + 1)), (uintptr_t)bp,
1077 ff))
1078 goto err;
1079 LIST_INSERT_HEAD(&d->chunk_dir[bucket][listnum], bp, entries);
1080
1081 if (bucket > 0 && d->malloc_junk != 0)
1082 memset(pp, SOME_FREEJUNK, MALLOC_PAGESIZE);
1083
1084 return bp;
1085
1086err:
1087 unmap(d, pp, MALLOC_PAGESIZE, 0);
1088 if (ff != NULL && ff != MAP_FAILED)
1089 unmap(d, ff, MALLOC_PAGESIZE, 0);
1090 return NULL;
1091}
1092
1093#if defined(__GNUC__) && __GNUC__ < 4
1094static inline unsigned int
1095lb(u_int x)
1096{
1097#if defined(__m88k__)
1098 __asm__ __volatile__ ("ff1 %0, %0" : "=r" (x) : "0" (x));
1099 return x;
1100#else
1101 /* portable version */
1102 unsigned int count = 0;
1103 while ((x & (1U << (sizeof(int) * CHAR_BIT - 1))) == 0) {
1104 count++;
1105 x <<= 1;
1106 }
1107 return (sizeof(int) * CHAR_BIT - 1) - count;
1108#endif
1109}
1110#else
1111/* using built-in function version */
1112static inline unsigned int
1113lb(u_int x)
1114{
1115 /* I need an extension just for integer-length (: */
1116 return (sizeof(int) * CHAR_BIT - 1) - __builtin_clz(x);
1117}
1118#endif
1119
1120/* https://pvk.ca/Blog/2015/06/27/linear-log-bucketing-fast-versatile-simple/
1121 via Tony Finch */
1122static inline unsigned int
1123bin_of(unsigned int size)
1124{
1125 const unsigned int linear = 6;
1126 const unsigned int subbin = 2;
1127
1128 unsigned int mask, rounded, rounded_size;
1129 unsigned int n_bits, shift;
1130
1131 n_bits = lb(size | (1U << linear));
1132 shift = n_bits - subbin;
1133 mask = (1ULL << shift) - 1;
1134 rounded = size + mask; /* XXX: overflow. */
1135
1136 rounded_size = rounded & ~mask;
1137 return rounded_size;
1138}
1139
1140static inline u_short
1141find_bucket(u_short size)
1142{
1143 /* malloc(0) is special */
1144 if (size == 0)
1145 return 0;
1146 if (size < MALLOC_MINSIZE)
1147 size = MALLOC_MINSIZE;
1148 if (mopts.def_maxcache != 0)
1149 size = bin_of(size);
1150 return howmany(size, MALLOC_MINSIZE);
1151}
1152
1153static void
1154fill_canary(char *ptr, size_t sz, size_t allocated)
1155{
1156 size_t check_sz = allocated - sz;
1157
1158 if (check_sz > CHUNK_CHECK_LENGTH)
1159 check_sz = CHUNK_CHECK_LENGTH;
1160 memset(ptr + sz, mopts.chunk_canaries, check_sz);
1161}
1162
1163/*
1164 * Allocate a chunk
1165 */
1166static void *
1167malloc_bytes(struct dir_info *d, size_t size)
1168{
1169 u_int i, j, k, r, bucket, listnum;
1170 u_short *lp;
1171 struct chunk_info *bp;
1172 void *p;
1173
1174 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
1175 d->canary1 != ~d->canary2)
1176 wrterror(d, "internal struct corrupt");
1177
1178 bucket = find_bucket(size);
1179
1180 r = getrbyte(d);
1181 listnum = r % MALLOC_CHUNK_LISTS;
1182
1183 /* If it's empty, make a page more of that size chunks */
1184 if ((bp = LIST_FIRST(&d->chunk_dir[bucket][listnum])) == NULL) {
1185 bp = omalloc_make_chunks(d, bucket, listnum);
1186 if (bp == NULL)
1187 return NULL;
1188 }
1189
1190 if (bp->canary != (u_short)d->canary1 || bucket != bp->bucket)
1191 wrterror(d, "chunk info corrupted");
1192
1193 r /= MALLOC_CHUNK_LISTS;
1194 /* do we need more random bits? */
1195 if (bp->total > 256 / MALLOC_CHUNK_LISTS)
1196 r = r << 8 | getrbyte(d);
1197 /* bias, as bp->total is not a power of 2 */
1198 i = r % bp->total;
1199
1200 j = i % MALLOC_BITS;
1201 i /= MALLOC_BITS;
1202 lp = &bp->bits[i];
1203 /* potentially start somewhere in a short */
1204 if (j > 0 && *lp >> j)
1205 k = ffs(*lp >> j) + j;
1206 else {
1207 /* no bit halfway, go to next full short */
1208 for (;;) {
1209 if (*lp) {
1210 k = ffs(*lp);
1211 break;
1212 }
1213 if (++i >= bp->offset)
1214 i = 0;
1215 lp = &bp->bits[i];
1216 }
1217 }
1218 *lp ^= 1 << --k;
1219
1220 /* If there are no more free, remove from free-list */
1221 if (--bp->free == 0)
1222 LIST_REMOVE(bp, entries);
1223
1224 /* Adjust to the real offset of that chunk */
1225 k += i * MALLOC_BITS;
1226
1227 if (mopts.chunk_canaries && size > 0)
1228 bp->bits[bp->offset + k] = size;
1229
1230 if (DO_STATS) {
1231 struct region_info *r = find(d, bp->page);
1232 STATS_SETFN(r, k, d->caller);
1233 }
1234
1235 p = (char *)bp->page + k * B2ALLOC(bucket);
1236 if (bucket > 0) {
1237 validate_junk(d, p, B2SIZE(bucket));
1238 if (mopts.chunk_canaries)
1239 fill_canary(p, size, B2SIZE(bucket));
1240 }
1241 return p;
1242}
1243
1244static void
1245validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
1246{
1247 size_t check_sz = allocated - sz;
1248 u_char *p, *q;
1249
1250 if (check_sz > CHUNK_CHECK_LENGTH)
1251 check_sz = CHUNK_CHECK_LENGTH;
1252 p = ptr + sz;
1253 q = p + check_sz;
1254
1255 while (p < q) {
1256 if (*p != (u_char)mopts.chunk_canaries && *p != SOME_JUNK) {
1257 wrterror(d, "canary corrupted %p[%tu]@%zu/%zu%s",
1258 ptr, p - ptr, sz, allocated,
1259 *p == SOME_FREEJUNK ? " (double free?)" : "");
1260 }
1261 p++;
1262 }
1263}
1264
1265static inline uint32_t
1266find_chunknum(struct dir_info *d, struct chunk_info *info, void *ptr, int check)
1267{
1268 uint32_t chunknum;
1269
1270 if (info->canary != (u_short)d->canary1)
1271 wrterror(d, "chunk info corrupted");
1272
1273 /* Find the chunk number on the page */
1274 chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) / B2ALLOC(info->bucket);
1275
1276 if ((uintptr_t)ptr & (MALLOC_MINSIZE - 1))
1277 wrterror(d, "modified chunk-pointer %p", ptr);
1278 if (CHUNK_FREE(info, chunknum))
1279 wrterror(d, "double free %p", ptr);
1280 if (check && info->bucket > 0) {
1281 validate_canary(d, ptr, info->bits[info->offset + chunknum],
1282 B2SIZE(info->bucket));
1283 }
1284 return chunknum;
1285}
1286
1287/*
1288 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1289 */
1290static void
1291free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
1292{
1293 struct chunk_head *mp;
1294 struct chunk_info *info;
1295 uint32_t chunknum;
1296 uint32_t listnum;
1297
1298 info = (struct chunk_info *)r->size;
1299 chunknum = find_chunknum(d, info, ptr, 0);
1300
1301 info->bits[chunknum / MALLOC_BITS] |= 1U << (chunknum % MALLOC_BITS);
1302 info->free++;
1303
1304 if (info->free == 1) {
1305 /* Page became non-full */
1306 listnum = getrbyte(d) % MALLOC_CHUNK_LISTS;
1307 mp = &d->chunk_dir[info->bucket][listnum];
1308 LIST_INSERT_HEAD(mp, info, entries);
1309 return;
1310 }
1311
1312 if (info->free != info->total)
1313 return;
1314
1315 LIST_REMOVE(info, entries);
1316
1317 if (info->bucket == 0 && !mopts.malloc_freeunmap)
1318 mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
1319 unmap(d, info->page, MALLOC_PAGESIZE, 0);
1320#ifdef MALLOC_STATS
1321 if (r->f != NULL) {
1322 unmap(d, r->f, MALLOC_PAGESIZE, MALLOC_PAGESIZE);
1323 r->f = NULL;
1324 }
1325#endif
1326
1327 delete(d, r);
1328 mp = &d->chunk_info_list[info->bucket];
1329 LIST_INSERT_HEAD(mp, info, entries);
1330}
1331
1332static void *
1333omalloc(struct dir_info *pool, size_t sz, int zero_fill)
1334{
1335 void *p, *caller = NULL;
1336 size_t psz;
1337
1338 if (sz > MALLOC_MAXCHUNK) {
1339 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1340 errno = ENOMEM;
1341 return NULL;
1342 }
1343 sz += mopts.malloc_guard;
1344 psz = PAGEROUND(sz);
1345 p = map(pool, psz, zero_fill);
1346 if (p == MAP_FAILED) {
1347 errno = ENOMEM;
1348 return NULL;
1349 }
1350#ifdef MALLOC_STATS
1351 if (DO_STATS)
1352 caller = pool->caller;
1353#endif
1354 if (insert(pool, p, sz, caller)) {
1355 unmap(pool, p, psz, 0);
1356 errno = ENOMEM;
1357 return NULL;
1358 }
1359 if (mopts.malloc_guard) {
1360 if (mprotect((char *)p + psz - mopts.malloc_guard,
1361 mopts.malloc_guard, PROT_NONE))
1362 wrterror(pool, "mprotect");
1363 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
1364 }
1365
1366 if (MALLOC_MOVE_COND(sz)) {
1367 /* fill whole allocation */
1368 if (pool->malloc_junk == 2)
1369 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1370 /* shift towards the end */
1371 p = MALLOC_MOVE(p, sz);
1372 /* fill zeros if needed and overwritten above */
1373 if (zero_fill && pool->malloc_junk == 2)
1374 memset(p, 0, sz - mopts.malloc_guard);
1375 } else {
1376 if (pool->malloc_junk == 2) {
1377 if (zero_fill)
1378 memset((char *)p + sz -
1379 mopts.malloc_guard, SOME_JUNK,
1380 psz - sz);
1381 else
1382 memset(p, SOME_JUNK,
1383 psz - mopts.malloc_guard);
1384 } else if (mopts.chunk_canaries)
1385 fill_canary(p, sz - mopts.malloc_guard,
1386 psz - mopts.malloc_guard);
1387 }
1388
1389 } else {
1390 /* takes care of SOME_JUNK */
1391 p = malloc_bytes(pool, sz);
1392 if (zero_fill && p != NULL && sz > 0)
1393 memset(p, 0, sz);
1394 }
1395
1396 return p;
1397}
1398
1399/*
1400 * Common function for handling recursion. Only
1401 * print the error message once, to avoid making the problem
1402 * potentially worse.
1403 */
1404static void
1405malloc_recurse(struct dir_info *d)
1406{
1407 static int noprint;
1408
1409 if (noprint == 0) {
1410 noprint = 1;
1411 wrterror(d, "recursive call");
1412 }
1413 d->active--;
1414 _MALLOC_UNLOCK(d->mutex);
1415 errno = EDEADLK;
1416}
1417
1418void
1419_malloc_init(int from_rthreads)
1420{
1421 u_int i, j, nmutexes;
1422 struct dir_info *d;
1423
1424 _MALLOC_LOCK(1);
1425 if (!from_rthreads && mopts.malloc_pool[1]) {
1426 _MALLOC_UNLOCK(1);
1427 return;
1428 }
1429 if (!mopts.malloc_canary) {
1430 char *p;
1431 size_t sz, roundup_sz, d_avail;
1432
1433 omalloc_init();
1434 /*
1435 * Allocate dir_infos with a guard page on either side. Also
1436 * randomise offset inside the page at which the dir_infos
1437 * lay (subject to alignment by 1 << MALLOC_MINSHIFT)
1438 */
1439 sz = mopts.malloc_mutexes * sizeof(*d);
1440 roundup_sz = (sz + MALLOC_PAGEMASK) & ~MALLOC_PAGEMASK;
1441 if ((p = MMAPNONE(roundup_sz + 2 * MALLOC_PAGESIZE, 0)) ==
1442 MAP_FAILED)
1443 wrterror(NULL, "malloc_init mmap1 failed");
1444 if (mprotect(p + MALLOC_PAGESIZE, roundup_sz,
1445 PROT_READ | PROT_WRITE))
1446 wrterror(NULL, "malloc_init mprotect1 failed");
1447 if (mimmutable(p, roundup_sz + 2 * MALLOC_PAGESIZE))
1448 wrterror(NULL, "malloc_init mimmutable1 failed");
1449 d_avail = (roundup_sz - sz) >> MALLOC_MINSHIFT;
1450 d = (struct dir_info *)(p + MALLOC_PAGESIZE +
1451 (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
1452 STATS_ADD(d[1].malloc_used, roundup_sz + 2 * MALLOC_PAGESIZE);
1453 for (i = 0; i < mopts.malloc_mutexes; i++)
1454 mopts.malloc_pool[i] = &d[i];
1455 mopts.internal_funcs = 1;
1456 if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0) {
1457 if (mprotect(&malloc_readonly, sizeof(malloc_readonly),
1458 PROT_READ))
1459 wrterror(NULL,
1460 "malloc_init mprotect r/o failed");
1461 if (mimmutable(&malloc_readonly,
1462 sizeof(malloc_readonly)))
1463 wrterror(NULL,
1464 "malloc_init mimmutable r/o failed");
1465 }
1466 }
1467
1468 nmutexes = from_rthreads ? mopts.malloc_mutexes : 2;
1469 for (i = 0; i < nmutexes; i++) {
1470 d = mopts.malloc_pool[i];
1471 d->malloc_mt = from_rthreads;
1472 if (d->canary1 == ~d->canary2)
1473 continue;
1474 if (i == 0) {
1475 omalloc_poolinit(d, MAP_CONCEAL);
1476 d->malloc_junk = 2;
1477 d->bigcache_size = 0;
1478 for (j = 0; j < MAX_SMALLCACHEABLE_SIZE; j++)
1479 d->smallcache[j].max = 0;
1480 } else {
1481 size_t sz = 0;
1482
1483 omalloc_poolinit(d, 0);
1484 d->malloc_junk = mopts.def_malloc_junk;
1485 d->bigcache_size = mopts.def_maxcache;
1486 for (j = 0; j < MAX_SMALLCACHEABLE_SIZE; j++) {
1487 d->smallcache[j].max =
1488 mopts.def_maxcache >> (j / 8);
1489 sz += d->smallcache[j].max * sizeof(void *);
1490 }
1491 sz += d->bigcache_size * sizeof(struct bigcache);
1492 if (sz > 0) {
1493 void *p = MMAP(sz, 0);
1494 if (p == MAP_FAILED)
1495 wrterror(NULL,
1496 "malloc_init mmap2 failed");
1497 if (mimmutable(p, sz))
1498 wrterror(NULL,
1499 "malloc_init mimmutable2 failed");
1500 for (j = 0; j < MAX_SMALLCACHEABLE_SIZE; j++) {
1501 d->smallcache[j].pages = p;
1502 p = (char *)p + d->smallcache[j].max *
1503 sizeof(void *);
1504 }
1505 d->bigcache = p;
1506 }
1507 }
1508 d->mutex = i;
1509 }
1510
1511 _MALLOC_UNLOCK(1);
1512}
1513DEF_STRONG(_malloc_init);
1514
1515#define PROLOGUE(p, fn) \
1516 d = (p); \
1517 if (d == NULL) { \
1518 _malloc_init(0); \
1519 d = (p); \
1520 } \
1521 _MALLOC_LOCK(d->mutex); \
1522 d->func = fn; \
1523 if (d->active++) { \
1524 malloc_recurse(d); \
1525 return NULL; \
1526 } \
1527
1528#define EPILOGUE() \
1529 d->active--; \
1530 _MALLOC_UNLOCK(d->mutex); \
1531 if (r == NULL && mopts.malloc_xmalloc) \
1532 wrterror(d, "out of memory"); \
1533 if (r != NULL) \
1534 errno = saved_errno; \
1535
1536void *
1537malloc(size_t size)
1538{
1539 void *r;
1540 struct dir_info *d;
1541 int saved_errno = errno;
1542
1543 PROLOGUE(getpool(), "malloc")
1544 SET_CALLER(d, caller(d));
1545 r = omalloc(d, size, 0);
1546 EPILOGUE()
1547 return r;
1548}
1549DEF_STRONG(malloc);
1550
1551void *
1552malloc_conceal(size_t size)
1553{
1554 void *r;
1555 struct dir_info *d;
1556 int saved_errno = errno;
1557
1558 PROLOGUE(mopts.malloc_pool[0], "malloc_conceal")
1559 SET_CALLER(d, caller(d));
1560 r = omalloc(d, size, 0);
1561 EPILOGUE()
1562 return r;
1563}
1564DEF_WEAK(malloc_conceal);
1565
1566static struct region_info *
1567findpool(void *p, struct dir_info *argpool, struct dir_info **foundpool,
1568 const char ** saved_function)
1569{
1570 struct dir_info *pool = argpool;
1571 struct region_info *r = find(pool, p);
1572
1573 if (r == NULL) {
1574 u_int i, nmutexes;
1575
1576 nmutexes = mopts.malloc_pool[1]->malloc_mt ?
1577 mopts.malloc_mutexes : 2;
1578 for (i = 1; i < nmutexes; i++) {
1579 u_int j = (argpool->mutex + i) & (nmutexes - 1);
1580
1581 pool->active--;
1582 _MALLOC_UNLOCK(pool->mutex);
1583 pool = mopts.malloc_pool[j];
1584 _MALLOC_LOCK(pool->mutex);
1585 pool->active++;
1586 r = find(pool, p);
1587 if (r != NULL) {
1588 *saved_function = pool->func;
1589 pool->func = argpool->func;
1590 break;
1591 }
1592 }
1593 if (r == NULL)
1594 wrterror(argpool, "bogus pointer (double free?) %p", p);
1595 }
1596 *foundpool = pool;
1597 return r;
1598}
1599
1600static void
1601ofree(struct dir_info **argpool, void *p, int clear, int check, size_t argsz)
1602{
1603 struct region_info *r;
1604 struct dir_info *pool;
1605 const char *saved_function;
1606 size_t sz;
1607
1608 r = findpool(p, *argpool, &pool, &saved_function);
1609
1610 REALSIZE(sz, r);
1611 if (pool->mmap_flag) {
1612 clear = 1;
1613 if (!check) {
1614 argsz = sz;
1615 if (sz > MALLOC_MAXCHUNK)
1616 argsz -= mopts.malloc_guard;
1617 }
1618 }
1619 if (check) {
1620 if (sz <= MALLOC_MAXCHUNK) {
1621 if (mopts.chunk_canaries && sz > 0) {
1622 struct chunk_info *info =
1623 (struct chunk_info *)r->size;
1624 uint32_t chunknum =
1625 find_chunknum(pool, info, p, 0);
1626
1627 if (info->bits[info->offset + chunknum] < argsz)
1628 wrterror(pool, "recorded size %hu"
1629 " < %zu",
1630 info->bits[info->offset + chunknum],
1631 argsz);
1632 } else {
1633 if (sz < argsz)
1634 wrterror(pool, "chunk size %zu < %zu",
1635 sz, argsz);
1636 }
1637 } else if (sz - mopts.malloc_guard < argsz) {
1638 wrterror(pool, "recorded size %zu < %zu",
1639 sz - mopts.malloc_guard, argsz);
1640 }
1641 }
1642 if (sz > MALLOC_MAXCHUNK) {
1643 if (!MALLOC_MOVE_COND(sz)) {
1644 if (r->p != p)
1645 wrterror(pool, "bogus pointer %p", p);
1646 if (mopts.chunk_canaries)
1647 validate_canary(pool, p,
1648 sz - mopts.malloc_guard,
1649 PAGEROUND(sz - mopts.malloc_guard));
1650 } else {
1651 /* shifted towards the end */
1652 if (p != MALLOC_MOVE(r->p, sz))
1653 wrterror(pool, "bogus moved pointer %p", p);
1654 p = r->p;
1655 }
1656 if (mopts.malloc_guard) {
1657 if (sz < mopts.malloc_guard)
1658 wrterror(pool, "guard size");
1659 if (!mopts.malloc_freeunmap) {
1660 if (mprotect((char *)p + PAGEROUND(sz) -
1661 mopts.malloc_guard, mopts.malloc_guard,
1662 PROT_READ | PROT_WRITE))
1663 wrterror(pool, "mprotect");
1664 }
1665 STATS_SUB(pool->malloc_guarded, mopts.malloc_guard);
1666 }
1667 unmap(pool, p, PAGEROUND(sz), clear ? argsz : 0);
1668 delete(pool, r);
1669 } else {
1670 void *tmp;
1671 u_int i;
1672
1673 /* Validate and optionally canary check */
1674 struct chunk_info *info = (struct chunk_info *)r->size;
1675 if (B2SIZE(info->bucket) != sz)
1676 wrterror(pool, "internal struct corrupt");
1677 find_chunknum(pool, info, p, mopts.chunk_canaries);
1678
1679 if (mopts.malloc_freecheck) {
1680 for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++) {
1681 tmp = pool->delayed_chunks[i];
1682 if (tmp == p)
1683 wrterror(pool,
1684 "double free %p", p);
1685 if (tmp != NULL) {
1686 size_t tmpsz;
1687
1688 r = find(pool, tmp);
1689 if (r == NULL)
1690 wrterror(pool,
1691 "bogus pointer ("
1692 "double free?) %p", tmp);
1693 REALSIZE(tmpsz, r);
1694 validate_junk(pool, tmp, tmpsz);
1695 }
1696 }
1697 }
1698
1699 if (clear && argsz > 0)
1700 explicit_bzero(p, argsz);
1701 junk_free(pool->malloc_junk, p, sz);
1702
1703 i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK;
1704 tmp = p;
1705 p = pool->delayed_chunks[i];
1706 if (tmp == p)
1707 wrterror(pool, "double free %p", p);
1708 pool->delayed_chunks[i] = tmp;
1709 if (p != NULL) {
1710 r = find(pool, p);
1711 if (r == NULL)
1712 wrterror(pool,
1713 "bogus pointer (double free?) %p", p);
1714 if (!mopts.malloc_freecheck) {
1715 REALSIZE(sz, r);
1716 validate_junk(pool, p, sz);
1717 }
1718 free_bytes(pool, r, p);
1719 }
1720 }
1721
1722 if (*argpool != pool) {
1723 pool->func = saved_function;
1724 *argpool = pool;
1725 }
1726}
1727
1728void
1729free(void *ptr)
1730{
1731 struct dir_info *d;
1732 int saved_errno = errno;
1733
1734 /* This is legal. */
1735 if (ptr == NULL)
1736 return;
1737
1738 d = getpool();
1739 if (d == NULL)
1740 wrterror(d, "free() called before allocation");
1741 _MALLOC_LOCK(d->mutex);
1742 d->func = "free";
1743 if (d->active++) {
1744 malloc_recurse(d);
1745 return;
1746 }
1747 ofree(&d, ptr, 0, 0, 0);
1748 d->active--;
1749 _MALLOC_UNLOCK(d->mutex);
1750 errno = saved_errno;
1751}
1752DEF_STRONG(free);
1753
1754static void
1755freezero_p(void *ptr, size_t sz)
1756{
1757 explicit_bzero(ptr, sz);
1758 free(ptr);
1759}
1760
1761void
1762freezero(void *ptr, size_t sz)
1763{
1764 struct dir_info *d;
1765 int saved_errno = errno;
1766
1767 /* This is legal. */
1768 if (ptr == NULL)
1769 return;
1770
1771 if (!mopts.internal_funcs) {
1772 freezero_p(ptr, sz);
1773 return;
1774 }
1775
1776 d = getpool();
1777 if (d == NULL)
1778 wrterror(d, "freezero() called before allocation");
1779 _MALLOC_LOCK(d->mutex);
1780 d->func = "freezero";
1781 if (d->active++) {
1782 malloc_recurse(d);
1783 return;
1784 }
1785 ofree(&d, ptr, 1, 1, sz);
1786 d->active--;
1787 _MALLOC_UNLOCK(d->mutex);
1788 errno = saved_errno;
1789}
1790DEF_WEAK(freezero);
1791
1792static void *
1793orealloc(struct dir_info **argpool, void *p, size_t newsz)
1794{
1795 struct region_info *r;
1796 struct dir_info *pool;
1797 const char *saved_function;
1798 struct chunk_info *info;
1799 size_t oldsz, goldsz, gnewsz;
1800 void *q, *ret;
1801 uint32_t chunknum;
1802 int forced;
1803
1804 if (p == NULL)
1805 return omalloc(*argpool, newsz, 0);
1806
1807 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1808 errno = ENOMEM;
1809 return NULL;
1810 }
1811
1812 r = findpool(p, *argpool, &pool, &saved_function);
1813
1814 REALSIZE(oldsz, r);
1815 if (oldsz <= MALLOC_MAXCHUNK) {
1816 if (DO_STATS || mopts.chunk_canaries) {
1817 info = (struct chunk_info *)r->size;
1818 chunknum = find_chunknum(pool, info, p, 0);
1819 }
1820 }
1821
1822 goldsz = oldsz;
1823 if (oldsz > MALLOC_MAXCHUNK) {
1824 if (oldsz < mopts.malloc_guard)
1825 wrterror(pool, "guard size");
1826 oldsz -= mopts.malloc_guard;
1827 }
1828
1829 gnewsz = newsz;
1830 if (gnewsz > MALLOC_MAXCHUNK)
1831 gnewsz += mopts.malloc_guard;
1832
1833 forced = mopts.malloc_realloc || pool->mmap_flag;
1834 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && !forced) {
1835 /* First case: from n pages sized allocation to m pages sized
1836 allocation, m > n */
1837 size_t roldsz = PAGEROUND(goldsz);
1838 size_t rnewsz = PAGEROUND(gnewsz);
1839
1840 if (rnewsz < roldsz && rnewsz > roldsz / 2 &&
1841 roldsz - rnewsz < mopts.def_maxcache * MALLOC_PAGESIZE &&
1842 !mopts.malloc_guard) {
1843
1844 ret = p;
1845 goto done;
1846 }
1847
1848 if (rnewsz > roldsz) {
1849 /* try to extend existing region */
1850 if (!mopts.malloc_guard) {
1851 void *hint = (char *)r->p + roldsz;
1852 size_t needed = rnewsz - roldsz;
1853
1854 STATS_INC(pool->cheap_realloc_tries);
1855 q = MMAPA(hint, needed, MAP_FIXED |
1856 __MAP_NOREPLACE | pool->mmap_flag);
1857 if (q == hint) {
1858 STATS_ADD(pool->malloc_used, needed);
1859 if (pool->malloc_junk == 2)
1860 memset(q, SOME_JUNK, needed);
1861 r->size = gnewsz;
1862 if (r->p != p) {
1863 /* old pointer is moved */
1864 memmove(r->p, p, oldsz);
1865 p = r->p;
1866 }
1867 if (mopts.chunk_canaries)
1868 fill_canary(p, newsz,
1869 PAGEROUND(newsz));
1870 STATS_SETF(r, (*argpool)->caller);
1871 STATS_INC(pool->cheap_reallocs);
1872 ret = p;
1873 goto done;
1874 }
1875 }
1876 } else if (rnewsz < roldsz) {
1877 /* shrink number of pages */
1878 if (mopts.malloc_guard) {
1879 if (mprotect((char *)r->p + rnewsz -
1880 mopts.malloc_guard, mopts.malloc_guard,
1881 PROT_NONE))
1882 wrterror(pool, "mprotect");
1883 }
1884 if (munmap((char *)r->p + rnewsz, roldsz - rnewsz))
1885 wrterror(pool, "munmap %p", (char *)r->p +
1886 rnewsz);
1887 STATS_SUB(pool->malloc_used, roldsz - rnewsz);
1888 r->size = gnewsz;
1889 if (MALLOC_MOVE_COND(gnewsz)) {
1890 void *pp = MALLOC_MOVE(r->p, gnewsz);
1891 memmove(pp, p, newsz);
1892 p = pp;
1893 } else if (mopts.chunk_canaries)
1894 fill_canary(p, newsz, PAGEROUND(newsz));
1895 STATS_SETF(r, (*argpool)->caller);
1896 ret = p;
1897 goto done;
1898 } else {
1899 /* number of pages remains the same */
1900 void *pp = r->p;
1901
1902 r->size = gnewsz;
1903 if (MALLOC_MOVE_COND(gnewsz))
1904 pp = MALLOC_MOVE(r->p, gnewsz);
1905 if (p != pp) {
1906 memmove(pp, p, oldsz < newsz ? oldsz : newsz);
1907 p = pp;
1908 }
1909 if (p == r->p) {
1910 if (newsz > oldsz && pool->malloc_junk == 2)
1911 memset((char *)p + newsz, SOME_JUNK,
1912 rnewsz - mopts.malloc_guard -
1913 newsz);
1914 if (mopts.chunk_canaries)
1915 fill_canary(p, newsz, PAGEROUND(newsz));
1916 }
1917 STATS_SETF(r, (*argpool)->caller);
1918 ret = p;
1919 goto done;
1920 }
1921 }
1922 if (oldsz <= MALLOC_MAXCHUNK && oldsz > 0 &&
1923 newsz <= MALLOC_MAXCHUNK && newsz > 0 &&
1924 !forced && find_bucket(newsz) == find_bucket(oldsz)) {
1925 /* do not reallocate if new size fits good in existing chunk */
1926 if (pool->malloc_junk == 2)
1927 memset((char *)p + newsz, SOME_JUNK, oldsz - newsz);
1928 if (mopts.chunk_canaries) {
1929 info->bits[info->offset + chunknum] = newsz;
1930 fill_canary(p, newsz, B2SIZE(info->bucket));
1931 }
1932 if (DO_STATS)
1933 STATS_SETFN(r, chunknum, (*argpool)->caller);
1934 ret = p;
1935 } else if (newsz != oldsz || forced) {
1936 /* create new allocation */
1937 q = omalloc(pool, newsz, 0);
1938 if (q == NULL) {
1939 ret = NULL;
1940 goto done;
1941 }
1942 if (newsz != 0 && oldsz != 0)
1943 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1944 ofree(&pool, p, 0, 0, 0);
1945 ret = q;
1946 } else {
1947 /* oldsz == newsz */
1948 if (newsz != 0)
1949 wrterror(pool, "realloc internal inconsistency");
1950 if (DO_STATS)
1951 STATS_SETFN(r, chunknum, (*argpool)->caller);
1952 ret = p;
1953 }
1954done:
1955 if (*argpool != pool) {
1956 pool->func = saved_function;
1957 *argpool = pool;
1958 }
1959 return ret;
1960}
1961
1962void *
1963realloc(void *ptr, size_t size)
1964{
1965 struct dir_info *d;
1966 void *r;
1967 int saved_errno = errno;
1968
1969 PROLOGUE(getpool(), "realloc")
1970 SET_CALLER(d, caller(d));
1971 r = orealloc(&d, ptr, size);
1972 EPILOGUE()
1973 return r;
1974}
1975DEF_STRONG(realloc);
1976
1977/*
1978 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1979 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1980 */
1981#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
1982
1983void *
1984calloc(size_t nmemb, size_t size)
1985{
1986 struct dir_info *d;
1987 void *r;
1988 int saved_errno = errno;
1989
1990 PROLOGUE(getpool(), "calloc")
1991 SET_CALLER(d, caller(d));
1992 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1993 nmemb > 0 && SIZE_MAX / nmemb < size) {
1994 d->active--;
1995 _MALLOC_UNLOCK(d->mutex);
1996 if (mopts.malloc_xmalloc)
1997 wrterror(d, "out of memory");
1998 errno = ENOMEM;
1999 return NULL;
2000 }
2001
2002 size *= nmemb;
2003 r = omalloc(d, size, 1);
2004 EPILOGUE()
2005 return r;
2006}
2007DEF_STRONG(calloc);
2008
2009void *
2010calloc_conceal(size_t nmemb, size_t size)
2011{
2012 struct dir_info *d;
2013 void *r;
2014 int saved_errno = errno;
2015
2016 PROLOGUE(mopts.malloc_pool[0], "calloc_conceal")
2017 SET_CALLER(d, caller(d));
2018 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
2019 nmemb > 0 && SIZE_MAX / nmemb < size) {
2020 d->active--;
2021 _MALLOC_UNLOCK(d->mutex);
2022 if (mopts.malloc_xmalloc)
2023 wrterror(d, "out of memory");
2024 errno = ENOMEM;
2025 return NULL;
2026 }
2027
2028 size *= nmemb;
2029 r = omalloc(d, size, 1);
2030 EPILOGUE()
2031 return r;
2032}
2033DEF_WEAK(calloc_conceal);
2034
2035static void *
2036orecallocarray(struct dir_info **argpool, void *p, size_t oldsize,
2037 size_t newsize)
2038{
2039 struct region_info *r;
2040 struct dir_info *pool;
2041 const char *saved_function;
2042 void *newptr;
2043 size_t sz;
2044
2045 if (p == NULL)
2046 return omalloc(*argpool, newsize, 1);
2047
2048 if (oldsize == newsize)
2049 return p;
2050
2051 r = findpool(p, *argpool, &pool, &saved_function);
2052
2053 REALSIZE(sz, r);
2054 if (sz <= MALLOC_MAXCHUNK) {
2055 if (mopts.chunk_canaries && sz > 0) {
2056 struct chunk_info *info = (struct chunk_info *)r->size;
2057 uint32_t chunknum = find_chunknum(pool, info, p, 0);
2058
2059 if (info->bits[info->offset + chunknum] != oldsize)
2060 wrterror(pool, "recorded size %hu != %zu",
2061 info->bits[info->offset + chunknum],
2062 oldsize);
2063 } else {
2064 if (sz < oldsize)
2065 wrterror(pool, "chunk size %zu < %zu",
2066 sz, oldsize);
2067 }
2068 } else {
2069 if (sz - mopts.malloc_guard < oldsize)
2070 wrterror(pool, "recorded size %zu < %zu",
2071 sz - mopts.malloc_guard, oldsize);
2072 if (oldsize < (sz - mopts.malloc_guard) / 2)
2073 wrterror(pool,
2074 "recorded size %zu inconsistent with %zu",
2075 sz - mopts.malloc_guard, oldsize);
2076 }
2077
2078 newptr = omalloc(pool, newsize, 0);
2079 if (newptr == NULL)
2080 goto done;
2081
2082 if (newsize > oldsize) {
2083 memcpy(newptr, p, oldsize);
2084 memset((char *)newptr + oldsize, 0, newsize - oldsize);
2085 } else
2086 memcpy(newptr, p, newsize);
2087
2088 ofree(&pool, p, 1, 0, oldsize);
2089
2090done:
2091 if (*argpool != pool) {
2092 pool->func = saved_function;
2093 *argpool = pool;
2094 }
2095
2096 return newptr;
2097}
2098
2099static void *
2100recallocarray_p(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
2101{
2102 size_t oldsize, newsize;
2103 void *newptr;
2104
2105 if (ptr == NULL)
2106 return calloc(newnmemb, size);
2107
2108 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
2109 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
2110 errno = ENOMEM;
2111 return NULL;
2112 }
2113 newsize = newnmemb * size;
2114
2115 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
2116 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
2117 errno = EINVAL;
2118 return NULL;
2119 }
2120 oldsize = oldnmemb * size;
2121
2122 /*
2123 * Don't bother too much if we're shrinking just a bit,
2124 * we do not shrink for series of small steps, oh well.
2125 */
2126 if (newsize <= oldsize) {
2127 size_t d = oldsize - newsize;
2128
2129 if (d < oldsize / 2 && d < MALLOC_PAGESIZE) {
2130 memset((char *)ptr + newsize, 0, d);
2131 return ptr;
2132 }
2133 }
2134
2135 newptr = malloc(newsize);
2136 if (newptr == NULL)
2137 return NULL;
2138
2139 if (newsize > oldsize) {
2140 memcpy(newptr, ptr, oldsize);
2141 memset((char *)newptr + oldsize, 0, newsize - oldsize);
2142 } else
2143 memcpy(newptr, ptr, newsize);
2144
2145 explicit_bzero(ptr, oldsize);
2146 free(ptr);
2147
2148 return newptr;
2149}
2150
2151void *
2152recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
2153{
2154 struct dir_info *d;
2155 size_t oldsize = 0, newsize;
2156 void *r;
2157 int saved_errno = errno;
2158
2159 if (!mopts.internal_funcs)
2160 return recallocarray_p(ptr, oldnmemb, newnmemb, size);
2161
2162 PROLOGUE(getpool(), "recallocarray")
2163 SET_CALLER(d, caller(d));
2164
2165 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
2166 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
2167 d->active--;
2168 _MALLOC_UNLOCK(d->mutex);
2169 if (mopts.malloc_xmalloc)
2170 wrterror(d, "out of memory");
2171 errno = ENOMEM;
2172 return NULL;
2173 }
2174 newsize = newnmemb * size;
2175
2176 if (ptr != NULL) {
2177 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
2178 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
2179 d->active--;
2180 _MALLOC_UNLOCK(d->mutex);
2181 errno = EINVAL;
2182 return NULL;
2183 }
2184 oldsize = oldnmemb * size;
2185 }
2186
2187 r = orecallocarray(&d, ptr, oldsize, newsize);
2188 EPILOGUE()
2189 return r;
2190}
2191DEF_WEAK(recallocarray);
2192
2193static void *
2194mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
2195{
2196 char *p, *q;
2197
2198 if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0)
2199 wrterror(d, "mapalign bad alignment");
2200 if (sz != PAGEROUND(sz))
2201 wrterror(d, "mapalign round");
2202
2203 /* Allocate sz + alignment bytes of memory, which must include a
2204 * subrange of size bytes that is properly aligned. Unmap the
2205 * other bytes, and then return that subrange.
2206 */
2207
2208 /* We need sz + alignment to fit into a size_t. */
2209 if (alignment > SIZE_MAX - sz)
2210 return MAP_FAILED;
2211
2212 p = map(d, sz + alignment, zero_fill);
2213 if (p == MAP_FAILED)
2214 return MAP_FAILED;
2215 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
2216 if (q != p) {
2217 if (munmap(p, q - p))
2218 wrterror(d, "munmap %p", p);
2219 }
2220 if (munmap(q + sz, alignment - (q - p)))
2221 wrterror(d, "munmap %p", q + sz);
2222 STATS_SUB(d->malloc_used, alignment);
2223
2224 return q;
2225}
2226
2227static void *
2228omemalign(struct dir_info *pool, size_t alignment, size_t sz, int zero_fill)
2229{
2230 size_t psz;
2231 void *p, *caller = NULL;
2232
2233 /* If between half a page and a page, avoid MALLOC_MOVE. */
2234 if (sz > MALLOC_MAXCHUNK && sz < MALLOC_PAGESIZE)
2235 sz = MALLOC_PAGESIZE;
2236 if (alignment <= MALLOC_PAGESIZE) {
2237 size_t pof2;
2238 /*
2239 * max(size, alignment) rounded up to power of 2 is enough
2240 * to assure the requested alignment. Large regions are
2241 * always page aligned.
2242 */
2243 if (sz < alignment)
2244 sz = alignment;
2245 if (sz < MALLOC_PAGESIZE) {
2246 pof2 = MALLOC_MINSIZE;
2247 while (pof2 < sz)
2248 pof2 <<= 1;
2249 } else
2250 pof2 = sz;
2251 return omalloc(pool, pof2, zero_fill);
2252 }
2253
2254 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
2255 errno = ENOMEM;
2256 return NULL;
2257 }
2258
2259 if (sz < MALLOC_PAGESIZE)
2260 sz = MALLOC_PAGESIZE;
2261 sz += mopts.malloc_guard;
2262 psz = PAGEROUND(sz);
2263
2264 p = mapalign(pool, alignment, psz, zero_fill);
2265 if (p == MAP_FAILED) {
2266 errno = ENOMEM;
2267 return NULL;
2268 }
2269
2270#ifdef MALLOC_STATS
2271 if (DO_STATS)
2272 caller = pool->caller;
2273#endif
2274 if (insert(pool, p, sz, caller)) {
2275 unmap(pool, p, psz, 0);
2276 errno = ENOMEM;
2277 return NULL;
2278 }
2279
2280 if (mopts.malloc_guard) {
2281 if (mprotect((char *)p + psz - mopts.malloc_guard,
2282 mopts.malloc_guard, PROT_NONE))
2283 wrterror(pool, "mprotect");
2284 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
2285 }
2286
2287 if (pool->malloc_junk == 2) {
2288 if (zero_fill)
2289 memset((char *)p + sz - mopts.malloc_guard,
2290 SOME_JUNK, psz - sz);
2291 else
2292 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
2293 } else if (mopts.chunk_canaries)
2294 fill_canary(p, sz - mopts.malloc_guard,
2295 psz - mopts.malloc_guard);
2296
2297 return p;
2298}
2299
2300int
2301posix_memalign(void **memptr, size_t alignment, size_t size)
2302{
2303 struct dir_info *d;
2304 int res, saved_errno = errno;
2305 void *r;
2306
2307 /* Make sure that alignment is a large enough power of 2. */
2308 if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *))
2309 return EINVAL;
2310
2311 d = getpool();
2312 if (d == NULL) {
2313 _malloc_init(0);
2314 d = getpool();
2315 }
2316 _MALLOC_LOCK(d->mutex);
2317 d->func = "posix_memalign";
2318 if (d->active++) {
2319 malloc_recurse(d);
2320 goto err;
2321 }
2322 SET_CALLER(d, caller(d));
2323 r = omemalign(d, alignment, size, 0);
2324 d->active--;
2325 _MALLOC_UNLOCK(d->mutex);
2326 if (r == NULL) {
2327 if (mopts.malloc_xmalloc)
2328 wrterror(d, "out of memory");
2329 goto err;
2330 }
2331 errno = saved_errno;
2332 *memptr = r;
2333 return 0;
2334
2335err:
2336 res = errno;
2337 errno = saved_errno;
2338 return res;
2339}
2340DEF_STRONG(posix_memalign);
2341
2342void *
2343aligned_alloc(size_t alignment, size_t size)
2344{
2345 struct dir_info *d;
2346 int saved_errno = errno;
2347 void *r;
2348
2349 /* Make sure that alignment is a positive power of 2. */
2350 if (((alignment - 1) & alignment) != 0 || alignment == 0) {
2351 errno = EINVAL;
2352 return NULL;
2353 }
2354 /* Per spec, size should be a multiple of alignment */
2355 if ((size & (alignment - 1)) != 0) {
2356 errno = EINVAL;
2357 return NULL;
2358 }
2359
2360 PROLOGUE(getpool(), "aligned_alloc")
2361 SET_CALLER(d, caller(d));
2362 r = omemalign(d, alignment, size, 0);
2363 EPILOGUE()
2364 return r;
2365}
2366DEF_STRONG(aligned_alloc);
2367
2368#ifdef MALLOC_STATS
2369
2370static int
2371btcmp(const struct btnode *e1, const struct btnode *e2)
2372{
2373 return memcmp(e1->caller, e2->caller, sizeof(e1->caller));
2374}
2375
2376RBT_GENERATE(btshead, btnode, entry, btcmp);
2377
2378static void*
2379store_caller(struct dir_info *d, struct btnode *f)
2380{
2381 struct btnode *p;
2382
2383 if (DO_STATS == 0 || d->btnodes == MAP_FAILED)
2384 return NULL;
2385
2386 p = RBT_FIND(btshead, &d->btraces, f);
2387 if (p != NULL)
2388 return p;
2389 if (d->btnodes == NULL ||
2390 d->btnodesused >= MALLOC_PAGESIZE / sizeof(struct btnode)) {
2391 d->btnodes = map(d, MALLOC_PAGESIZE, 0);
2392 if (d->btnodes == MAP_FAILED)
2393 return NULL;
2394 d->btnodesused = 0;
2395 }
2396 p = &d->btnodes[d->btnodesused++];
2397 memcpy(p->caller, f->caller, sizeof(p->caller[0]) * DO_STATS);
2398 RBT_INSERT(btshead, &d->btraces, p);
2399 return p;
2400}
2401
2402static void fabstorel(const void *, char *, size_t);
2403
2404static void
2405print_chunk_details(struct dir_info *pool, void *p, size_t sz, size_t index)
2406{
2407 struct region_info *r;
2408 struct chunk_info *chunkinfo;
2409 struct btnode* btnode;
2410 uint32_t chunknum;
2411 int frame;
2412 char buf1[128];
2413 char buf2[128];
2414 const char *msg = "";
2415
2416 r = find(pool, p);
2417 chunkinfo = (struct chunk_info *)r->size;
2418 chunknum = find_chunknum(pool, chunkinfo, p, 0);
2419 btnode = (struct btnode *)r->f[chunknum];
2420 frame = DO_STATS - 1;
2421 if (btnode != NULL)
2422 fabstorel(btnode->caller[frame], buf1, sizeof(buf1));
2423 strlcpy(buf2, ". 0x0", sizeof(buf2));
2424 if (chunknum > 0) {
2425 chunknum--;
2426 btnode = (struct btnode *)r->f[chunknum];
2427 if (btnode != NULL)
2428 fabstorel(btnode->caller[frame], buf2, sizeof(buf2));
2429 if (CHUNK_FREE(chunkinfo, chunknum))
2430 msg = " (now free)";
2431 }
2432
2433 wrterror(pool,
2434 "write to free chunk %p[%zu..%zu]@%zu allocated at %s "
2435 "(preceding chunk %p allocated at %s%s)",
2436 p, index * sizeof(uint64_t), (index + 1) * sizeof(uint64_t) - 1,
2437 sz, buf1, p - sz, buf2, msg);
2438}
2439
2440static void
2441ulog(const char *format, ...)
2442{
2443 va_list ap;
2444 static char* buf;
2445 static size_t filled;
2446 int len;
2447
2448 if (buf == NULL)
2449 buf = MMAP(KTR_USER_MAXLEN, 0);
2450 if (buf == MAP_FAILED)
2451 return;
2452
2453 va_start(ap, format);
2454 len = vsnprintf(buf + filled, KTR_USER_MAXLEN - filled, format, ap);
2455 va_end(ap);
2456 if (len < 0)
2457 return;
2458 if ((size_t)len > KTR_USER_MAXLEN - filled)
2459 len = KTR_USER_MAXLEN - filled;
2460 filled += len;
2461 if (filled > 0) {
2462 if (filled == KTR_USER_MAXLEN || buf[filled - 1] == '\n') {
2463 utrace("malloc", buf, filled);
2464 filled = 0;
2465 }
2466 }
2467}
2468
2469struct malloc_leak {
2470 void *f;
2471 size_t total_size;
2472 int count;
2473};
2474
2475struct leaknode {
2476 RBT_ENTRY(leaknode) entry;
2477 struct malloc_leak d;
2478};
2479
2480static inline int
2481leakcmp(const struct leaknode *e1, const struct leaknode *e2)
2482{
2483 return e1->d.f < e2->d.f ? -1 : e1->d.f > e2->d.f;
2484}
2485
2486RBT_HEAD(leaktree, leaknode);
2487RBT_PROTOTYPE(leaktree, leaknode, entry, leakcmp);
2488RBT_GENERATE(leaktree, leaknode, entry, leakcmp);
2489
2490static void
2491wrtwarning(const char *func, char *msg, ...)
2492{
2493 int saved_errno = errno;
2494 va_list ap;
2495
2496 dprintf(STDERR_FILENO, "%s(%d) in %s(): ", __progname,
2497 getpid(), func != NULL ? func : "unknown");
2498 va_start(ap, msg);
2499 vdprintf(STDERR_FILENO, msg, ap);
2500 va_end(ap);
2501 dprintf(STDERR_FILENO, "\n");
2502
2503 errno = saved_errno;
2504}
2505
2506static void
2507putleakinfo(struct leaktree *leaks, void *f, size_t sz, int cnt)
2508{
2509 struct leaknode key, *p;
2510 static struct leaknode *page;
2511 static unsigned int used;
2512
2513 if (cnt == 0 || page == MAP_FAILED)
2514 return;
2515
2516 key.d.f = f;
2517 p = RBT_FIND(leaktree, leaks, &key);
2518 if (p == NULL) {
2519 if (page == NULL ||
2520 used >= MALLOC_PAGESIZE / sizeof(struct leaknode)) {
2521 page = MMAP(MALLOC_PAGESIZE, 0);
2522 if (page == MAP_FAILED) {
2523 wrtwarning(__func__, strerror(errno));
2524 return;
2525 }
2526 used = 0;
2527 }
2528 p = &page[used++];
2529 p->d.f = f;
2530 p->d.total_size = sz * cnt;
2531 p->d.count = cnt;
2532 RBT_INSERT(leaktree, leaks, p);
2533 } else {
2534 p->d.total_size += sz * cnt;
2535 p->d.count += cnt;
2536 }
2537}
2538
2539static void
2540fabstorel(const void *f, char *buf, size_t size)
2541{
2542 Dl_info info;
2543 const char *object = ".";
2544 const char *caller;
2545
2546 caller = f;
2547 if (caller != NULL && dladdr(f, &info) != 0) {
2548 caller -= (uintptr_t)info.dli_fbase;
2549 object = info.dli_fname;
2550 }
2551 snprintf(buf, size, "%s %p", object, caller);
2552}
2553
2554static void
2555dump_leak(struct leaknode *p)
2556{
2557 int i;
2558 char buf[128];
2559
2560 if (p->d.f == NULL) {
2561 fabstorel(NULL, buf, sizeof(buf));
2562 ulog("%18p %7zu %6u %6zu addr2line -e %s\n",
2563 p->d.f, p->d.total_size, p->d.count,
2564 p->d.total_size / p->d.count, buf);
2565 return;
2566 }
2567
2568 for (i = 0; i < DO_STATS; i++) {
2569 const char *abscaller;
2570
2571 abscaller = ((struct btnode*)p->d.f)->caller[i];
2572 if (abscaller == NULL)
2573 break;
2574 fabstorel(abscaller, buf, sizeof(buf));
2575 if (i == 0)
2576 ulog("%18p %7zu %6u %6zu addr2line -e %s\n",
2577 abscaller, p->d.total_size, p->d.count,
2578 p->d.total_size / p->d.count, buf);
2579 else
2580 ulog("%*p %*s %6s %6s addr2line -e %s\n",
2581 i + 18, abscaller, 7 - i, "-", "-", "-", buf);
2582 }
2583}
2584
2585static void
2586dump_leaks(struct leaktree *leaks)
2587{
2588 struct leaknode *p;
2589
2590 ulog("Leak report:\n");
2591 ulog(" f sum # avg\n");
2592
2593 RBT_FOREACH(p, leaktree, leaks)
2594 dump_leak(p);
2595}
2596
2597static void
2598dump_chunk(struct leaktree* leaks, struct chunk_info *p, void **f,
2599 int fromfreelist)
2600{
2601 while (p != NULL) {
2602 if (mopts.malloc_verbose)
2603 ulog("chunk %18p %18p %4zu %d/%d\n",
2604 p->page, NULL,
2605 B2SIZE(p->bucket), p->free, p->total);
2606 if (!fromfreelist) {
2607 size_t i, sz = B2SIZE(p->bucket);
2608 for (i = 0; i < p->total; i++) {
2609 if (!CHUNK_FREE(p, i))
2610 putleakinfo(leaks, f[i], sz, 1);
2611 }
2612 break;
2613 }
2614 p = LIST_NEXT(p, entries);
2615 if (mopts.malloc_verbose && p != NULL)
2616 ulog(" ->");
2617 }
2618}
2619
2620static void
2621dump_free_chunk_info(struct dir_info *d, struct leaktree *leaks)
2622{
2623 u_int i, j, count;
2624 struct chunk_info *p;
2625
2626 ulog("Free chunk structs:\n");
2627 ulog("Bkt) #CI page"
2628 " f size free/n\n");
2629 for (i = 0; i <= BUCKETS; i++) {
2630 count = 0;
2631 LIST_FOREACH(p, &d->chunk_info_list[i], entries)
2632 count++;
2633 for (j = 0; j < MALLOC_CHUNK_LISTS; j++) {
2634 p = LIST_FIRST(&d->chunk_dir[i][j]);
2635 if (p == NULL && count == 0)
2636 continue;
2637 if (j == 0)
2638 ulog("%3d) %3d ", i, count);
2639 else
2640 ulog(" ");
2641 if (p != NULL)
2642 dump_chunk(leaks, p, NULL, 1);
2643 else
2644 ulog(".\n");
2645 }
2646 }
2647
2648}
2649
2650static void
2651dump_free_page_info(struct dir_info *d)
2652{
2653 struct smallcache *cache;
2654 size_t i, total = 0;
2655
2656 ulog("Cached in small cache:\n");
2657 for (i = 0; i < MAX_SMALLCACHEABLE_SIZE; i++) {
2658 cache = &d->smallcache[i];
2659 if (cache->length != 0)
2660 ulog("%zu(%u): %u = %zu\n", i + 1, cache->max,
2661 cache->length, cache->length * (i + 1));
2662 total += cache->length * (i + 1);
2663 }
2664
2665 ulog("Cached in big cache: %zu/%zu\n", d->bigcache_used,
2666 d->bigcache_size);
2667 for (i = 0; i < d->bigcache_size; i++) {
2668 if (d->bigcache[i].psize != 0)
2669 ulog("%zu: %zu\n", i, d->bigcache[i].psize);
2670 total += d->bigcache[i].psize;
2671 }
2672 ulog("Free pages cached: %zu\n", total);
2673}
2674
2675static void
2676malloc_dump1(int poolno, struct dir_info *d, struct leaktree *leaks)
2677{
2678 size_t i, realsize;
2679
2680 if (mopts.malloc_verbose) {
2681 ulog("Malloc dir of %s pool %d at %p\n", __progname, poolno, d);
2682 ulog("MT=%d J=%d Fl=%#x\n", d->malloc_mt, d->malloc_junk,
2683 d->mmap_flag);
2684 ulog("Region slots free %zu/%zu\n",
2685 d->regions_free, d->regions_total);
2686 ulog("Inserts %zu/%zu\n", d->inserts, d->insert_collisions);
2687 ulog("Deletes %zu/%zu\n", d->deletes, d->delete_moves);
2688 ulog("Cheap reallocs %zu/%zu\n",
2689 d->cheap_reallocs, d->cheap_realloc_tries);
2690 ulog("In use %zu\n", d->malloc_used);
2691 ulog("Guarded %zu\n", d->malloc_guarded);
2692 dump_free_chunk_info(d, leaks);
2693 dump_free_page_info(d);
2694 ulog("Hash table:\n");
2695 ulog("slot) hash d type page "
2696 "f size [free/n]\n");
2697 }
2698 for (i = 0; i < d->regions_total; i++) {
2699 if (d->r[i].p != NULL) {
2700 size_t h = hash(d->r[i].p) &
2701 (d->regions_total - 1);
2702 if (mopts.malloc_verbose)
2703 ulog("%4zx) #%4zx %zd ",
2704 i, h, h - i);
2705 REALSIZE(realsize, &d->r[i]);
2706 if (realsize > MALLOC_MAXCHUNK) {
2707 putleakinfo(leaks, d->r[i].f, realsize, 1);
2708 if (mopts.malloc_verbose)
2709 ulog("pages %18p %18p %zu\n", d->r[i].p,
2710 d->r[i].f, realsize);
2711 } else
2712 dump_chunk(leaks,
2713 (struct chunk_info *)d->r[i].size,
2714 d->r[i].f, 0);
2715 }
2716 }
2717 if (mopts.malloc_verbose)
2718 ulog("\n");
2719}
2720
2721static void
2722malloc_dump0(int poolno, struct dir_info *pool, struct leaktree *leaks)
2723{
2724 int i;
2725 void *p;
2726 struct region_info *r;
2727
2728 if (pool == NULL || pool->r == NULL)
2729 return;
2730 for (i = 0; i < MALLOC_DELAYED_CHUNK_MASK + 1; i++) {
2731 p = pool->delayed_chunks[i];
2732 if (p == NULL)
2733 continue;
2734 r = find(pool, p);
2735 if (r == NULL)
2736 wrterror(pool, "bogus pointer in malloc_dump %p", p);
2737 free_bytes(pool, r, p);
2738 pool->delayed_chunks[i] = NULL;
2739 }
2740 malloc_dump1(poolno, pool, leaks);
2741}
2742
2743void
2744malloc_dump(void)
2745{
2746 u_int i;
2747 int saved_errno = errno;
2748
2749 /* XXX leak when run multiple times */
2750 struct leaktree leaks = RBT_INITIALIZER(&leaks);
2751
2752 for (i = 0; i < mopts.malloc_mutexes; i++)
2753 malloc_dump0(i, mopts.malloc_pool[i], &leaks);
2754
2755 dump_leaks(&leaks);
2756 ulog("\n");
2757 errno = saved_errno;
2758}
2759DEF_WEAK(malloc_dump);
2760
2761static void
2762malloc_exit(void)
2763{
2764 int save_errno = errno;
2765
2766 ulog("******** Start dump %s *******\n", __progname);
2767 ulog("M=%u I=%d F=%d U=%d J=%d R=%d X=%d C=%#x cache=%u "
2768 "G=%zu\n",
2769 mopts.malloc_mutexes,
2770 mopts.internal_funcs, mopts.malloc_freecheck,
2771 mopts.malloc_freeunmap, mopts.def_malloc_junk,
2772 mopts.malloc_realloc, mopts.malloc_xmalloc,
2773 mopts.chunk_canaries, mopts.def_maxcache,
2774 mopts.malloc_guard);
2775
2776 malloc_dump();
2777 ulog("******** End dump %s *******\n", __progname);
2778 errno = save_errno;
2779}
2780
2781#endif /* MALLOC_STATS */
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
deleted file mode 100644
index d60317ce08..0000000000
--- a/src/lib/libc/stdlib/merge.c
+++ /dev/null
@@ -1,336 +0,0 @@
1/* $OpenBSD: merge.c,v 1.10 2015/06/21 03:20:56 millert 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 if (nmemb == 0)
105 return (0);
106
107 /*
108 * XXX
109 * Stupid subtraction for the Cray.
110 */
111 iflag = 0;
112 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
113 iflag = 1;
114
115 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
116 return (-1);
117
118 list1 = base;
119 setup(list1, list2, nmemb, size, cmp);
120 last = list2 + nmemb * size;
121 i = big = 0;
122 while (*EVAL(list2) != last) {
123 l2 = list1;
124 p1 = EVAL(list1);
125 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
126 p2 = *EVAL(p2);
127 f1 = l2;
128 f2 = l1 = list1 + (p2 - list2);
129 if (p2 != last)
130 p2 = *EVAL(p2);
131 l2 = list1 + (p2 - list2);
132 while (f1 < l1 && f2 < l2) {
133 if ((*cmp)(f1, f2) <= 0) {
134 q = f2;
135 b = f1, t = l1;
136 sense = -1;
137 } else {
138 q = f1;
139 b = f2, t = l2;
140 sense = 0;
141 }
142 if (!big) { /* here i = 0 */
143 while ((b += size) < t && cmp(q, b) >sense)
144 if (++i == 6) {
145 big = 1;
146 goto EXPONENTIAL;
147 }
148 } else {
149EXPONENTIAL: for (i = size; ; i <<= 1)
150 if ((p = (b + i)) >= t) {
151 if ((p = t - size) > b &&
152 (*cmp)(q, p) <= sense)
153 t = p;
154 else
155 b = p;
156 break;
157 } else if ((*cmp)(q, p) <= sense) {
158 t = p;
159 if (i == size)
160 big = 0;
161 goto FASTCASE;
162 } else
163 b = p;
164 while (t > b+size) {
165 i = (((t - b) / size) >> 1) * size;
166 if ((*cmp)(q, p = b + i) <= sense)
167 t = p;
168 else
169 b = p;
170 }
171 goto COPY;
172FASTCASE: while (i > size)
173 if ((*cmp)(q,
174 p = b + (i >>= 1)) <= sense)
175 t = p;
176 else
177 b = p;
178COPY: b = t;
179 }
180 i = size;
181 if (q == f1) {
182 if (iflag) {
183 ICOPY_LIST(f2, tp2, b);
184 ICOPY_ELT(f1, tp2, i);
185 } else {
186 CCOPY_LIST(f2, tp2, b);
187 CCOPY_ELT(f1, tp2, i);
188 }
189 } else {
190 if (iflag) {
191 ICOPY_LIST(f1, tp2, b);
192 ICOPY_ELT(f2, tp2, i);
193 } else {
194 CCOPY_LIST(f1, tp2, b);
195 CCOPY_ELT(f2, tp2, i);
196 }
197 }
198 }
199 if (f2 < l2) {
200 if (iflag)
201 ICOPY_LIST(f2, tp2, l2);
202 else
203 CCOPY_LIST(f2, tp2, l2);
204 } else if (f1 < l1) {
205 if (iflag)
206 ICOPY_LIST(f1, tp2, l1);
207 else
208 CCOPY_LIST(f1, tp2, l1);
209 }
210 *p1 = l2;
211 }
212 tp2 = list1; /* swap list1, list2 */
213 list1 = list2;
214 list2 = tp2;
215 last = list2 + nmemb*size;
216 }
217 if (base == list2) {
218 memmove(list2, list1, nmemb*size);
219 list2 = list1;
220 }
221 free(list2);
222 return (0);
223}
224
225#define swap(a, b) { \
226 s = b; \
227 i = size; \
228 do { \
229 tmp = *a; *a++ = *s; *s++ = tmp; \
230 } while (--i); \
231 a -= size; \
232 }
233#define reverse(bot, top) { \
234 s = top; \
235 do { \
236 i = size; \
237 do { \
238 tmp = *bot; *bot++ = *s; *s++ = tmp; \
239 } while (--i); \
240 s -= size2; \
241 } while(bot < s); \
242}
243
244/*
245 * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
246 * increasing order, list2 in a corresponding linked list. Checks for runs
247 * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
248 * is defined. Otherwise simple pairwise merging is used.)
249 */
250void
251setup(u_char *list1, u_char *list2, size_t n, size_t size,
252 int (*cmp)(const void *, const void *))
253{
254 int i, length, size2, sense;
255 u_char tmp, *f1, *f2, *s, *l2, *last, *p2;
256
257 size2 = size*2;
258 if (n <= 5) {
259 insertionsort(list1, n, size, cmp);
260 *EVAL(list2) = (u_char*) list2 + n*size;
261 return;
262 }
263 /*
264 * Avoid running pointers out of bounds; limit n to evens
265 * for simplicity.
266 */
267 i = 4 + (n & 1);
268 insertionsort(list1 + (n - i) * size, i, size, cmp);
269 last = list1 + size * (n - i);
270 *EVAL(list2 + (last - list1)) = list2 + n * size;
271
272#ifdef NATURAL
273 p2 = list2;
274 f1 = list1;
275 sense = (cmp(f1, f1 + size) > 0);
276 for (; f1 < last; sense = !sense) {
277 length = 2;
278 /* Find pairs with same sense. */
279 for (f2 = f1 + size2; f2 < last; f2 += size2) {
280 if ((cmp(f2, f2+ size) > 0) != sense)
281 break;
282 length += 2;
283 }
284 if (length < THRESHOLD) { /* Pairwise merge */
285 do {
286 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
287 if (sense > 0)
288 swap (f1, f1 + size);
289 } while ((f1 += size2) < f2);
290 } else { /* Natural merge */
291 l2 = f2;
292 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
293 if ((cmp(f2-size, f2) > 0) != sense) {
294 p2 = *EVAL(p2) = f2 - list1 + list2;
295 if (sense > 0)
296 reverse(f1, f2-size);
297 f1 = f2;
298 }
299 }
300 if (sense > 0)
301 reverse (f1, f2-size);
302 f1 = f2;
303 if (f2 < last || cmp(f2 - size, f2) > 0)
304 p2 = *EVAL(p2) = f2 - list1 + list2;
305 else
306 p2 = *EVAL(p2) = list2 + n*size;
307 }
308 }
309#else /* pairwise merge only. */
310 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
311 p2 = *EVAL(p2) = p2 + size2;
312 if (cmp (f1, f1 + size) > 0)
313 swap(f1, f1 + size);
314 }
315#endif /* NATURAL */
316}
317
318/*
319 * This is to avoid out-of-bounds addresses in sorting the
320 * last 4 elements.
321 */
322static void
323insertionsort(u_char *a, size_t n, size_t size,
324 int (*cmp)(const void *, const void *))
325{
326 u_char *ai, *s, *t, *u, tmp;
327 int i;
328
329 for (ai = a+size; --n >= 1; ai += size)
330 for (t = ai; t > a; t -= size) {
331 u = t - size;
332 if (cmp(u, t) <= 0)
333 break;
334 swap(u, t);
335 }
336}
diff --git a/src/lib/libc/stdlib/mkdtemp.c b/src/lib/libc/stdlib/mkdtemp.c
deleted file mode 100644
index c11501f893..0000000000
--- a/src/lib/libc/stdlib/mkdtemp.c
+++ /dev/null
@@ -1,41 +0,0 @@
1/* $OpenBSD: mkdtemp.c,v 1.2 2024/03/01 21:30:40 millert Exp $ */
2/*
3 * Copyright (c) 2024 Todd C. Miller
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
18#include <sys/stat.h>
19#include <stdlib.h>
20
21static int
22mkdtemp_cb(const char *path, int flags)
23{
24 return mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
25}
26
27char *
28mkdtemp(char *path)
29{
30 if (__mktemp4(path, 0, 0, mkdtemp_cb) == 0)
31 return path;
32 return NULL;
33}
34
35char *
36mkdtemps(char *path, int slen)
37{
38 if (__mktemp4(path, slen, 0, mkdtemp_cb) == 0)
39 return path;
40 return NULL;
41}
diff --git a/src/lib/libc/stdlib/mkstemp.c b/src/lib/libc/stdlib/mkstemp.c
deleted file mode 100644
index 75a9d27d1a..0000000000
--- a/src/lib/libc/stdlib/mkstemp.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/* $OpenBSD: mkstemp.c,v 1.1 2024/01/19 19:45:02 millert Exp $ */
2/*
3 * Copyright (c) 2024 Todd C. Miller
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
18#include <sys/stat.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <stdlib.h>
22
23#define MKOSTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC)
24
25static int
26mkstemp_cb(const char *path, int flags)
27{
28 flags |= O_CREAT | O_EXCL | O_RDWR;
29 return open(path, flags, S_IRUSR|S_IWUSR);
30}
31
32int
33mkostemps(char *path, int slen, int flags)
34{
35 if (flags & ~MKOSTEMP_FLAGS) {
36 errno = EINVAL;
37 return -1;
38 }
39 return __mktemp4(path, slen, flags, mkstemp_cb);
40}
41
42int
43mkostemp(char *path, int flags)
44{
45 if (flags & ~MKOSTEMP_FLAGS) {
46 errno = EINVAL;
47 return -1;
48 }
49 return __mktemp4(path, 0, flags, mkstemp_cb);
50}
51DEF_WEAK(mkostemp);
52
53int
54mkstemp(char *path)
55{
56 return __mktemp4(path, 0, 0, mkstemp_cb);
57}
58DEF_WEAK(mkstemp);
59
60int
61mkstemps(char *path, int slen)
62{
63 return __mktemp4(path, slen, 0, mkstemp_cb);
64}
diff --git a/src/lib/libc/stdlib/mktemp.3 b/src/lib/libc/stdlib/mktemp.3
deleted file mode 100644
index 83b7c9eb30..0000000000
--- a/src/lib/libc/stdlib/mktemp.3
+++ /dev/null
@@ -1,431 +0,0 @@
1.\" $OpenBSD: mktemp.3,v 1.2 2024/03/01 21:30:40 millert 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.Dd $Mdocdate: March 1 2024 $
31.Dt MKTEMP 3
32.Os
33.Sh NAME
34.Nm mktemp ,
35.Nm mkstemp ,
36.Nm mkostemp ,
37.Nm mkstemps ,
38.Nm mkostemps ,
39.Nm mkdtemp ,
40.Nm mkdtemps
41.Nd make temporary file name (unique)
42.Sh SYNOPSIS
43.In stdlib.h
44.Ft char *
45.Fn mktemp "char *template"
46.Ft int
47.Fn mkstemp "char *template"
48.Ft int
49.Fn mkstemps "char *template" "int suffixlen"
50.Ft char *
51.Fn mkdtemp "char *template"
52.Ft char *
53.Fn mkdtemps "char *template" "int suffixlen"
54.In stdlib.h
55.In fcntl.h
56.Ft int
57.Fn mkostemp "char *template" "int flags"
58.Ft int
59.Fn mkostemps "char *template" "int suffixlen" "int flags"
60.Sh DESCRIPTION
61The
62.Fn mktemp
63family of functions take the given file name template and overwrite
64a portion of it to create a new file name.
65This file name is unique and suitable for use by the application.
66The template may be any file name with at least six trailing
67.Em X Ns s ,
68for example
69.Pa /tmp/temp.XXXXXXXX .
70The trailing
71.Em X Ns s
72are replaced with a unique digit and letter combination.
73The number of unique file names that can be returned
74depends on the number of
75.Em X Ns s
76provided;
77.Fn mktemp
78will try at least 2 ** 31 combinations before giving up.
79At least six
80.Em X Ns s
81must be used, though 10 is much better.
82.Pp
83The
84.Fn mktemp
85function generates a temporary file name based on a template as
86described above.
87Because
88.Fn mktemp
89does not actually create the temporary file, there is a window of
90opportunity during which another process can open the file instead.
91Because of this race condition,
92.Fn mktemp
93should not be used where
94.Fn mkstemp
95can be used instead.
96.Fn mktemp
97was marked as a legacy interface in
98.St -p1003.1-2001 .
99.Pp
100The
101.Fn mkstemp
102function makes the same replacement to the template and creates the template
103file, mode 0600, returning a file descriptor opened for reading and writing.
104This avoids the race between testing for a file's existence and opening it
105for use.
106.Pp
107The
108.Fn mkostemp
109function acts the same as
110.Fn mkstemp ,
111except that the
112.Fa flags
113argument may contain zero or more of the following flags for the underlying
114.Xr open 2
115system call:
116.Pp
117.Bl -tag -width "O_CLOEXECXX" -offset indent -compact
118.It Dv O_APPEND
119Append on each write.
120.It Dv O_CLOEXEC
121Set the close-on-exec flag on the new file descriptor.
122.It Dv O_SYNC
123Perform synchronous I/O operations.
124.El
125.Pp
126The
127.Fn mkstemps
128and
129.Fn mkostemps
130functions act the same as
131.Fn mkstemp
132and
133.Fn mkostemp ,
134except they permit a suffix to exist in the template.
135The template should be of the form
136.Pa /tmp/tmpXXXXXXXXXXsuffix .
137.Fn mkstemps
138and
139.Fn mkostemps
140are told the length of the suffix string, i.e.,
141.Li strlen("suffix") .
142.Pp
143The
144.Fn mkdtemp
145function makes the same replacement to the template as in
146.Fn mktemp
147and creates the template directory, mode 0700.
148The
149.Fn mkdtemps
150function acts the same as
151.Fn mkdtemp ,
152except that it permits a suffix to exist in the template,
153similar to
154.Fn mkstemps .
155.Sh RETURN VALUES
156The
157.Fn mktemp ,
158.Fn mkdtemp ,
159and
160.Fn mkdtemps
161functions return a pointer to the template on success and
162.Dv NULL
163on failure.
164The
165.Fn mkstemp ,
166.Fn mkostemp ,
167.Fn mkstemps ,
168and
169.Fn mkostemps
170functions return \-1 if no suitable file could be created.
171If any call fails, an error code is placed in the global variable
172.Va errno .
173.Sh EXAMPLES
174Quite often a programmer will want to replace a use of
175.Fn mktemp
176with
177.Fn mkstemp ,
178usually to avoid the problems described above.
179Doing this correctly requires a good understanding of the code in question.
180.Pp
181For instance, code of this form:
182.Bd -literal -offset indent
183char sfn[19];
184FILE *sfp;
185
186strlcpy(sfn, "/tmp/ed.XXXXXXXXXX", sizeof(sfn));
187if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL) {
188 warn("%s", sfn);
189 return (NULL);
190}
191return (sfp);
192.Ed
193.Pp
194should be rewritten like this:
195.Bd -literal -offset indent
196char sfn[19];
197FILE *sfp;
198int fd;
199
200strlcpy(sfn, "/tmp/ed.XXXXXXXXXX", sizeof(sfn));
201if ((fd = mkstemp(sfn)) == -1 ||
202 (sfp = fdopen(fd, "w+")) == NULL) {
203 if (fd != -1) {
204 unlink(sfn);
205 close(fd);
206 }
207 warn("%s", sfn);
208 return (NULL);
209}
210return (sfp);
211.Ed
212.Pp
213Often one will find code which uses
214.Fn mktemp
215very early on, perhaps to globally initialize the template nicely, but the
216code which calls
217.Xr open 2
218or
219.Xr fopen 3
220on that file name will occur much later.
221(In almost all cases, the use of
222.Xr fopen 3
223will mean that the flags
224.Dv O_CREAT
225|
226.Dv O_EXCL
227are not given to
228.Xr open 2 ,
229and thus a symbolic link race becomes possible, hence making
230necessary the use of
231.Xr fdopen 3
232as seen above.)
233Furthermore, one must be careful about code which opens, closes, and then
234re-opens the file in question.
235Finally, one must ensure that upon error the temporary file is
236removed correctly.
237.Pp
238There are also cases where modifying the code to use
239.Fn mktemp ,
240in concert with
241.Xr open 2
242using the flags
243.Dv O_CREAT
244|
245.Dv O_EXCL ,
246is better, as long as the code retries a new template if
247.Xr open 2
248fails with an
249.Va errno
250of
251.Er EEXIST .
252.Sh ERRORS
253The
254.Fn mktemp ,
255.Fn mkstemp ,
256.Fn mkostemp ,
257and
258.Fn mkdtemp
259functions may set
260.Va errno
261to one of the following values:
262.Bl -tag -width Er
263.It Bq Er EINVAL
264The
265.Ar template
266argument has fewer than six trailing
267.Em X Ns s .
268.It Bq Er EEXIST
269All file names tried are already in use.
270Consider appending more
271.Em X Ns s to the
272.Ar template .
273.El
274.Pp
275The
276.Fn mkstemps
277and
278.Fn mkostemps
279functions may set
280.Va errno
281to
282.Bl -tag -width Er
283.It Bq Er EINVAL
284The
285.Ar template
286argument length is less than
287.Ar suffixlen
288or it has fewer than six
289.Em X Ns s
290before the suffix.
291.It Bq Er EEXIST
292All file names tried are already in use.
293Consider appending more
294.Em X Ns s to the
295.Ar template .
296.El
297.Pp
298In addition, the
299.Fn mkostemp
300and
301.Fn mkostemps
302functions may also set
303.Va errno
304to
305.Bl -tag -width Er
306.It Bq Er EINVAL
307.Fa flags
308is invalid.
309.El
310.Pp
311The
312.Fn mktemp
313function may also set
314.Va errno
315to any value specified by the
316.Xr lstat 2
317function.
318.Pp
319The
320.Fn mkstemp ,
321.Fn mkostemp ,
322.Fn mkstemps ,
323and
324.Fn mkostemps
325functions may also set
326.Va errno
327to any value specified by the
328.Xr open 2
329function.
330.Pp
331The
332.Fn mkdtemp
333function may also set
334.Va errno
335to any value specified by the
336.Xr mkdir 2
337function.
338.Sh SEE ALSO
339.Xr chmod 2 ,
340.Xr lstat 2 ,
341.Xr mkdir 2 ,
342.Xr open 2 ,
343.Xr tempnam 3 ,
344.Xr tmpfile 3 ,
345.Xr tmpnam 3
346.Sh STANDARDS
347The
348.Fn mkdtemp
349and
350.Fn mkstemp
351functions conform to the
352.St -p1003.1-2008
353specification.
354The ability to specify more than six
355.Em X Ns s
356is an extension to that standard.
357The
358.Fn mkostemp
359function is expected to conform to a future revision of that standard.
360.Pp
361The
362.Fn mktemp
363function conforms to
364.St -p1003.1-2001 ;
365as of
366.St -p1003.1-2008
367it is no longer a part of the standard.
368.Pp
369The
370.Fn mkstemps ,
371.Fn mkostemps ,
372and
373.Fn mkdtemps
374functions are non-standard and should not be used if portability is required.
375.Sh HISTORY
376A
377.Fn mktemp
378function appeared in
379.At v7 .
380The
381.Fn mkdtemp
382function appeared in
383.Ox 2.2 .
384The
385.Fn mkstemp
386function appeared in
387.Bx 4.3 .
388The
389.Fn mkstemps
390function appeared in
391.Ox 2.3 .
392The
393.Fn mkostemp
394and
395.Fn mkostemps
396functions appeared in
397.Ox 5.7 .
398The
399.Fn mkdtemps
400function appeared in
401.Ox 7.5 .
402.Sh BUGS
403For
404.Fn mktemp
405there is an obvious race between file name selection and file
406creation and deletion: the program is typically written to call
407.Xr tmpnam 3 ,
408.Xr tempnam 3 ,
409or
410.Fn mktemp .
411Subsequently, the program calls
412.Xr open 2
413or
414.Xr fopen 3
415and erroneously opens a file (or symbolic link, FIFO or other
416device) that the attacker has created in the expected file location.
417Hence
418.Fn mkstemp
419is recommended, since it atomically creates the file.
420An attacker can guess the file names produced by
421.Fn mktemp .
422Whenever it is possible,
423.Fn mkstemp
424or
425.Fn mkdtemp
426should be used instead.
427.Pp
428For this reason,
429.Xr ld 1
430will output a warning message whenever it links code that uses
431.Fn mktemp .
diff --git a/src/lib/libc/stdlib/mktemp.c b/src/lib/libc/stdlib/mktemp.c
deleted file mode 100644
index 4dc06f74d1..0000000000
--- a/src/lib/libc/stdlib/mktemp.c
+++ /dev/null
@@ -1,48 +0,0 @@
1/* $OpenBSD: mktemp.c,v 1.2 2024/01/19 19:45:02 millert Exp $ */
2/*
3 * Copyright (c) 2024 Todd C. Miller
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
18#include <sys/stat.h>
19#include <errno.h>
20#include <stdlib.h>
21
22static int
23mktemp_cb(const char *path, int flags)
24{
25 struct stat sb;
26
27 if (lstat(path, &sb) == 0)
28 errno = EEXIST;
29 return (errno == ENOENT ? 0 : -1);
30}
31
32/* Also called via tmpnam(3) and tempnam(3). */
33char *
34_mktemp(char *path)
35{
36 if (__mktemp4(path, 0, 0, mktemp_cb) == 0)
37 return path;
38 return NULL;
39}
40
41__warn_references(mktemp,
42 "mktemp() possibly used unsafely; consider using mkstemp()");
43
44char *
45mktemp(char *path)
46{
47 return _mktemp(path);
48}
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
deleted file mode 100644
index 3334e2ad2b..0000000000
--- a/src/lib/libc/stdlib/mrand48.c
+++ /dev/null
@@ -1,24 +0,0 @@
1/* $OpenBSD: mrand48.c,v 1.6 2015/08/27 04:33:31 guenther 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
18mrand48(void)
19{
20 if (__rand48_deterministic == 0)
21 return (int)arc4random();
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
deleted file mode 100644
index f1f548c3af..0000000000
--- a/src/lib/libc/stdlib/nrand48.c
+++ /dev/null
@@ -1,22 +0,0 @@
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
deleted file mode 100644
index fcd0a4cbdb..0000000000
--- a/src/lib/libc/stdlib/posix_memalign.3
+++ /dev/null
@@ -1,97 +0,0 @@
1.\" $OpenBSD: posix_memalign.3,v 1.4 2017/05/13 07:11:29 otto 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: May 13 2017 $
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 ,
60.Xr reallocarray 3
61and
62.Xr free 3 ,
63but not
64.Xr recallocarray 3
65and
66.Xr freezero 3 .
67.Sh RETURN VALUES
68The
69.Fn posix_memalign
70function returns the value 0 if successful; otherwise it returns an error value.
71.Sh ERRORS
72The
73.Fn posix_memalign
74function will fail if:
75.Bl -tag -width Er
76.It Bq Er EINVAL
77The
78.Fa alignment
79parameter is not a power of 2 at least as large as
80.Fn sizeof "void *" .
81.It Bq Er ENOMEM
82Memory allocation error.
83.El
84.Sh SEE ALSO
85.Xr free 3 ,
86.Xr malloc 3 ,
87.Xr realloc 3
88.Sh STANDARDS
89The
90.Fn posix_memalign
91function conforms to
92.St -p1003.1-2001 .
93.Sh HISTORY
94The
95.Fn posix_memalign
96function first appeared in
97.Ox 4.8 .
diff --git a/src/lib/libc/stdlib/posix_openpt.3 b/src/lib/libc/stdlib/posix_openpt.3
deleted file mode 100644
index b55e1be750..0000000000
--- a/src/lib/libc/stdlib/posix_openpt.3
+++ /dev/null
@@ -1,102 +0,0 @@
1.\" $OpenBSD: posix_openpt.3,v 1.4 2019/01/25 00:19:25 millert Exp $
2.\"
3.\" Copyright (c) 2012 Todd C. Miller <millert@openbsd.org>
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: January 25 2019 $
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
deleted file mode 100644
index e45ab6ebd0..0000000000
--- a/src/lib/libc/stdlib/posix_pty.c
+++ /dev/null
@@ -1,120 +0,0 @@
1/* $OpenBSD: posix_pty.c,v 1.3 2019/01/25 00:19:25 millert Exp $ */
2
3/*
4 * Copyright (c) 2012 Todd C. Miller <millert@openbsd.org>
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_ACCMODE) != O_RDWR ||
39 (oflag & ~(O_ACCMODE | O_NOCTTY)) != 0) {
40 errno = EINVAL;
41 return -1;
42 }
43
44 /* Get pty master and slave (this API only uses the master). */
45 fd = open(PATH_PTMDEV, O_RDWR);
46 if (fd != -1) {
47 if (ioctl(fd, PTMGET, &ptm) != -1) {
48 close(ptm.sfd);
49 mfd = ptm.cfd;
50 }
51 close(fd);
52 }
53
54 return mfd;
55}
56
57/*
58 * Look up the name of the specified pty master fd.
59 * Note that the name returned does *not* include the /dev/ prefix.
60 * Returns the name on success and NULL on error, setting errno.
61 */
62static const char *
63ptmname(int mfd)
64{
65 struct stat sb;
66 const char *name;
67
68 /* Make sure it is a pty master. */
69 if (fstat(mfd, &sb) != 0)
70 return NULL;
71 if (!S_ISCHR(sb.st_mode)) {
72 errno = EINVAL;
73 return NULL;
74 }
75 name = devname(sb.st_rdev, S_IFCHR);
76 if (strncmp(name, "pty", 3) != 0) {
77 errno = EINVAL;
78 return NULL;
79 }
80 return name;
81}
82
83/*
84 * The PTMGET ioctl handles the mode and owner for us.
85 */
86int
87grantpt(int mfd)
88{
89 return ptmname(mfd) ? 0 : -1;
90}
91
92/*
93 * The PTMGET ioctl unlocks the pty master and slave for us.
94 */
95int
96unlockpt(int mfd)
97{
98 return ptmname(mfd) ? 0 : -1;
99}
100
101/*
102 * Look up the path of the slave pty that corresponds to the master fd.
103 * Returns the path if successful or NULL on error.
104 */
105char *
106ptsname(int mfd)
107{
108 const char *master;
109 static char slave[sizeof(((struct ptmget *)NULL)->sn)];
110
111 if ((master = ptmname(mfd)) == NULL)
112 return NULL;
113
114 /* Add /dev/ prefix and convert "pty" to "tty". */
115 strlcpy(slave, _PATH_DEV, sizeof(slave));
116 strlcat(slave, master, sizeof(slave));
117 slave[sizeof(_PATH_DEV) - 1] = 't';
118
119 return slave;
120}
diff --git a/src/lib/libc/stdlib/ptsname.3 b/src/lib/libc/stdlib/ptsname.3
deleted file mode 100644
index 98705528f5..0000000000
--- a/src/lib/libc/stdlib/ptsname.3
+++ /dev/null
@@ -1,160 +0,0 @@
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/qsort.3 b/src/lib/libc/stdlib/qsort.3
deleted file mode 100644
index 4c0cddaccb..0000000000
--- a/src/lib/libc/stdlib/qsort.3
+++ /dev/null
@@ -1,276 +0,0 @@
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.27 2020/02/08 01:09:57 jsg Exp $
33.\"
34.Dd $Mdocdate: February 8 2020 $
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 int 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 and will fall back to
115.Fn heapsort
116if the recursion depth exceeds 2 lg N.
117.Pp
118The
119.Fn heapsort
120function is an implementation of J.W.J. William's
121.Dq heapsort
122algorithm,
123a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
124.Fn heapsort
125takes O N lg N worst-case time.
126This implementation of
127.Fn heapsort
128is implemented without recursive function calls.
129.Pp
130The function
131.Fn mergesort
132requires additional memory of size
133.Fa nmemb *
134.Fa size
135bytes; it should be used only when space is not at a premium.
136.Fn mergesort
137is optimized for data with pre-existing order; its worst case
138time is O N lg N; its best case is O N.
139.Pp
140Normally,
141.Fn qsort
142is faster than
143.Fn mergesort ,
144which is faster than
145.Fn heapsort .
146Memory availability and pre-existing order in the data can make this untrue.
147.Sh RETURN VALUES
148.Rv -std heapsort mergesort
149.Sh EXAMPLES
150.Bd -literal
151#include <stdio.h>
152#include <stdlib.h>
153#include <string.h>
154
155char *array[] = { "XX", "YYY", "Z" };
156#define N (sizeof(array) / sizeof(array[0]))
157
158int
159cmp(const void *a, const void *b)
160{
161 /*
162 * a and b point to elements of the array.
163 * Cast and dereference to obtain the actual elements,
164 * which are also pointers in this case.
165 */
166 size_t lena = strlen(*(const char **)a);
167 size_t lenb = strlen(*(const char **)b);
168 /*
169 * Do not subtract the lengths. The difference between values
170 * cannot be represented by an int.
171 */
172 return lena < lenb ? -1 : lena > lenb;
173}
174
175int
176main()
177{
178 size_t i;
179
180 qsort(array, N, sizeof(array[0]), cmp);
181 for (i = 0; i < N; i++)
182 printf("%s\en", array[i]);
183}
184.Ed
185.Pp
186It is almost always an error to use subtraction to compute the return value
187of the comparison function.
188.Sh ERRORS
189The
190.Fn heapsort
191and
192.Fn mergesort
193functions succeed unless:
194.Bl -tag -width Er
195.It Bq Er EINVAL
196The
197.Fa size
198argument is zero, or the
199.Fa size
200argument to
201.Fn mergesort
202is less than
203.Dq "sizeof(void *) / 2" .
204.It Bq Er ENOMEM
205.Fn heapsort
206or
207.Fn mergesort
208were unable to allocate memory.
209.El
210.Sh SEE ALSO
211.Xr sort 1 ,
212.Xr radixsort 3
213.Rs
214.%A Hoare, C.A.R.
215.%D 1962
216.%T "Quicksort"
217.%J "The Computer Journal"
218.%V 5:1
219.%P pp. 10-15
220.Re
221.Rs
222.%A Williams, J.W.J
223.%D 1964
224.%T "Heapsort"
225.%J "Communications of the ACM"
226.%V 7:1
227.%P pp. 347\-348
228.Re
229.Rs
230.%A Knuth, D.E.
231.%D 1968
232.%B "The Art of Computer Programming"
233.%V Vol. 3
234.%T "Sorting and Searching"
235.%P pp. 114\-123, 145\-149
236.Re
237.Rs
238.%A McIlroy, P.M.
239.%T "Optimistic Sorting and Information Theoretic Complexity"
240.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
241.%P pp. 467\-464
242.%D January 1993
243.Re
244.Rs
245.%A Bentley, J.L.
246.%A McIlroy, M.D.
247.%T "Engineering a Sort Function"
248.%J "Software \- Practice and Experience"
249.%V Vol. 23(11)
250.%P pp. 1249\-1265
251.%D November 1993
252.Re
253.Rs
254.%A Musser, D.
255.%T "Introspective Sorting and Selection Algorithms"
256.%J "Software \- Practice and Experience"
257.%V Vol. 27(8)
258.%P pp. 983\-993
259.%D August 1997
260.Re
261.Sh STANDARDS
262Previous versions of
263.Fn qsort
264did not permit the comparison routine itself to call
265.Fn qsort .
266This is no longer true.
267.Pp
268The
269.Fn qsort
270function conforms to
271.St -ansiC .
272.Sh HISTORY
273A
274.Fn qsort
275function first appeared in
276.At v2 .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
deleted file mode 100644
index ca73e67f29..0000000000
--- a/src/lib/libc/stdlib/qsort.c
+++ /dev/null
@@ -1,238 +0,0 @@
1/* $OpenBSD: qsort.c,v 1.18 2017/05/30 14:54:09 millert 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 * This version differs from Bentley & McIlroy in the following ways:
43 * 1. The partition value is swapped into a[0] instead of being
44 * stored out of line.
45 *
46 * 2. The swap function can swap 32-bit aligned elements on 64-bit
47 * platforms instead of swapping them as byte-aligned.
48 *
49 * 3. It uses David Musser's introsort algorithm to fall back to
50 * heapsort(3) when the recursion depth reaches 2*lg(n + 1).
51 * This avoids quicksort's quadratic behavior for pathological
52 * input without appreciably changing the average run time.
53 *
54 * 4. Tail recursion is eliminated when sorting the larger of two
55 * subpartitions to save stack space.
56 */
57#define SWAPTYPE_BYTEV 1
58#define SWAPTYPE_INTV 2
59#define SWAPTYPE_LONGV 3
60#define SWAPTYPE_INT 4
61#define SWAPTYPE_LONG 5
62
63#define TYPE_ALIGNED(TYPE, a, es) \
64 (((char *)a - (char *)0) % sizeof(TYPE) == 0 && es % sizeof(TYPE) == 0)
65
66#define swapcode(TYPE, parmi, parmj, n) { \
67 size_t i = (n) / sizeof (TYPE); \
68 TYPE *pi = (TYPE *) (parmi); \
69 TYPE *pj = (TYPE *) (parmj); \
70 do { \
71 TYPE t = *pi; \
72 *pi++ = *pj; \
73 *pj++ = t; \
74 } while (--i > 0); \
75}
76
77static __inline void
78swapfunc(char *a, char *b, size_t n, int swaptype)
79{
80 switch (swaptype) {
81 case SWAPTYPE_INT:
82 case SWAPTYPE_INTV:
83 swapcode(int, a, b, n);
84 break;
85 case SWAPTYPE_LONG:
86 case SWAPTYPE_LONGV:
87 swapcode(long, a, b, n);
88 break;
89 default:
90 swapcode(char, a, b, n);
91 break;
92 }
93}
94
95#define swap(a, b) do { \
96 switch (swaptype) { \
97 case SWAPTYPE_INT: { \
98 int t = *(int *)(a); \
99 *(int *)(a) = *(int *)(b); \
100 *(int *)(b) = t; \
101 break; \
102 } \
103 case SWAPTYPE_LONG: { \
104 long t = *(long *)(a); \
105 *(long *)(a) = *(long *)(b); \
106 *(long *)(b) = t; \
107 break; \
108 } \
109 default: \
110 swapfunc(a, b, es, swaptype); \
111 } \
112} while (0)
113
114#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
115
116static __inline char *
117med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
118{
119 return cmp(a, b) < 0 ?
120 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
121 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
122}
123
124static void
125introsort(char *a, size_t n, size_t es, size_t maxdepth, int swaptype,
126 int (*cmp)(const void *, const void *))
127{
128 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
129 int cmp_result;
130 size_t r, s;
131
132loop: if (n < 7) {
133 for (pm = a + es; pm < a + n * es; pm += es)
134 for (pl = pm; pl > a && cmp(pl - es, pl) > 0;
135 pl -= es)
136 swap(pl, pl - es);
137 return;
138 }
139 if (maxdepth == 0) {
140 if (heapsort(a, n, es, cmp) == 0)
141 return;
142 }
143 maxdepth--;
144 pm = a + (n / 2) * es;
145 if (n > 7) {
146 pl = a;
147 pn = a + (n - 1) * es;
148 if (n > 40) {
149 s = (n / 8) * es;
150 pl = med3(pl, pl + s, pl + 2 * s, cmp);
151 pm = med3(pm - s, pm, pm + s, cmp);
152 pn = med3(pn - 2 * s, pn - s, pn, cmp);
153 }
154 pm = med3(pl, pm, pn, cmp);
155 }
156 swap(a, pm);
157 pa = pb = a + es;
158 pc = pd = a + (n - 1) * es;
159 for (;;) {
160 while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
161 if (cmp_result == 0) {
162 swap(pa, pb);
163 pa += es;
164 }
165 pb += es;
166 }
167 while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
168 if (cmp_result == 0) {
169 swap(pc, pd);
170 pd -= es;
171 }
172 pc -= es;
173 }
174 if (pb > pc)
175 break;
176 swap(pb, pc);
177 pb += es;
178 pc -= es;
179 }
180
181 pn = a + n * es;
182 r = min(pa - a, pb - pa);
183 vecswap(a, pb - r, r);
184 r = min(pd - pc, pn - pd - es);
185 vecswap(pb, pn - r, r);
186 /*
187 * To save stack space we sort the smaller side of the partition first
188 * using recursion and eliminate tail recursion for the larger side.
189 */
190 r = pb - pa;
191 s = pd - pc;
192 if (r < s) {
193 /* Recurse for 1st side, iterate for 2nd side. */
194 if (s > es) {
195 if (r > es) {
196 introsort(a, r / es, es, maxdepth,
197 swaptype, cmp);
198 }
199 a = pn - s;
200 n = s / es;
201 goto loop;
202 }
203 } else {
204 /* Recurse for 2nd side, iterate for 1st side. */
205 if (r > es) {
206 if (s > es) {
207 introsort(pn - s, s / es, es, maxdepth,
208 swaptype, cmp);
209 }
210 n = r / es;
211 goto loop;
212 }
213 }
214}
215
216void
217qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *))
218{
219 size_t i, maxdepth = 0;
220 int swaptype;
221
222 /* Approximate 2*ceil(lg(n + 1)) */
223 for (i = n; i > 0; i >>= 1)
224 maxdepth++;
225 maxdepth *= 2;
226
227 if (TYPE_ALIGNED(long, a, es))
228 swaptype = es == sizeof(long) ? SWAPTYPE_LONG : SWAPTYPE_LONGV;
229 else if (sizeof(int) != sizeof(long) && TYPE_ALIGNED(int, a, es))
230 swaptype = es == sizeof(int) ? SWAPTYPE_INT : SWAPTYPE_INTV;
231 else
232 swaptype = SWAPTYPE_BYTEV;
233
234 introsort(a, n, es, maxdepth, swaptype, cmp);
235
236}
237
238DEF_STRONG(qsort);
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
deleted file mode 100644
index 7290142a9c..0000000000
--- a/src/lib/libc/stdlib/radixsort.3
+++ /dev/null
@@ -1,151 +0,0 @@
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.14 2022/08/04 06:20:24 jsg Exp $
29.\"
30.Dd $Mdocdate: August 4 2022 $
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
81ASCII order of the byte strings they reference and
82.Fa endbyte
83has a sorting weight of 0.
84.Pp
85The
86.Fn sradixsort
87function is stable; that is, if two elements compare as equal, their
88order in the sorted array is unchanged.
89The
90.Fn sradixsort
91function uses additional memory sufficient to hold
92.Fa nmemb
93pointers.
94.Pp
95The
96.Fn radixsort
97function is not stable, but uses no additional memory.
98.Pp
99These functions are variants of most-significant-byte radix sorting; in
100particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
101They take linear time relative to the number of bytes in the strings.
102.Sh RETURN VALUES
103.Rv -std
104.Sh ERRORS
105.Bl -tag -width Er
106.It Bq Er EINVAL
107The value of the
108.Fa endbyte
109element of
110.Fa table
111is not 0 or 255.
112.El
113.Pp
114Additionally, the
115.Fn sradixsort
116function may fail and set
117.Va errno
118for any of the errors specified for the library routine
119.Xr malloc 3 .
120.Sh SEE ALSO
121.Xr sort 1 ,
122.Xr qsort 3
123.Rs
124.%A Knuth, D.E.
125.%D 1968
126.%B "The Art of Computer Programming"
127.%T "Sorting and Searching"
128.%V Vol. 3
129.%P pp. 170-178
130.Re
131.Rs
132.%A Paige, R.
133.%D 1987
134.%T "Three Partition Refinement Algorithms"
135.%J "SIAM J. Comput."
136.%V Vol. 16
137.%N No. 6
138.Re
139.Rs
140.%A McIlroy, P.
141.%D 1993
142.%B "Engineering Radix Sort"
143.%T "Computing Systems"
144.%V Vol. 6:1
145.%P pp. 5-27
146.Re
147.Sh HISTORY
148The
149.Fn radixsort
150function first appeared in
151.Bx 4.3 Net/2 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
deleted file mode 100644
index 49d03b52d5..0000000000
--- a/src/lib/libc/stdlib/radixsort.c
+++ /dev/null
@@ -1,294 +0,0 @@
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
deleted file mode 100644
index cf7dde8536..0000000000
--- a/src/lib/libc/stdlib/rand.3
+++ /dev/null
@@ -1,135 +0,0 @@
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.21 2022/03/29 18:15:52 naddy Exp $
33.\"
34.Dd $Mdocdate: March 29 2022 $
35.Dt RAND 3
36.Os
37.Sh NAME
38.Nm rand ,
39.Nm rand_r ,
40.Nm srand ,
41.Nm srand_deterministic
42.Nd bad pseudo-random number generator
43.Sh SYNOPSIS
44.In stdlib.h
45.Ft void
46.Fn srand "unsigned int seed"
47.Ft void
48.Fn srand_deterministic "unsigned int seed"
49.Ft int
50.Fn rand void
51.Ft int
52.Fn rand_r "unsigned int *seed"
53.Sh DESCRIPTION
54.Bf -symbolic
55Standards insist that this interface return deterministic results.
56Unsafe usage is very common, so
57.Ox
58changed the subsystem to return non-deterministic results by default.
59.Ef
60.Pp
61To satisfy portable code,
62.Fn srand
63may be called to initialize the subsystem.
64In
65.Ox
66the
67.Ar seed
68variable is ignored, and strong random number results will be provided from
69.Xr arc4random 3 .
70In other systems, the
71.Ar seed
72variable primes a simplistic deterministic algorithm.
73.Pp
74If the standardized behavior is required
75.Fn srand_deterministic
76can be substituted for
77.Fn srand ,
78then subsequent
79.Fn rand
80calls will return results using the deterministic algorithm.
81The deterministic sequence algorithm changed a number of times since
82original development, is underspecified, and should not be relied upon to
83remain consistent between platforms and over time.
84.Pp
85The
86.Fn rand
87function returns a result in the range of 0 to
88.Dv RAND_MAX .
89By default, this result comes from
90.Xr arc4random 3 .
91If
92.Fn srand_deterministic
93was called, the result will be computed using the deterministic algorithm.
94.Pp
95The
96.Fn rand_r
97function is a thread-safe version of
98.Fn rand .
99Storage for the seed must be provided through the
100.Fa seed
101argument, and needs to have been initialized by the caller.
102It always operates using the deterministic algorithm.
103.Sh SEE ALSO
104.Xr arc4random 3 ,
105.Xr rand48 3 ,
106.Xr random 3
107.Sh STANDARDS
108The
109.Fn rand
110function conforms to
111.St -ansiC .
112.Pp
113The
114.Fn rand_r
115function conforms to
116.St -p1003.1-2008 .
117.Pp
118The
119.Fn srand
120function does not conform to
121.St -ansiC ,
122intentionally.
123.Pp
124The
125.Fn srand_deterministic
126function is an
127.Ox
128extension.
129.Sh HISTORY
130The functions
131.Fn rand
132and
133.Fn srand
134first appeared in
135.At v3 .
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
deleted file mode 100644
index 97964f6ef9..0000000000
--- a/src/lib/libc/stdlib/rand.c
+++ /dev/null
@@ -1,74 +0,0 @@
1/* $OpenBSD: rand.c,v 1.18 2017/11/28 06:55:49 tb 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 <stdlib.h>
33
34static int rand_deterministic;
35static u_int next = 1;
36
37int
38rand_r(u_int *seed)
39{
40 *seed = *seed * 1103515245 + 12345;
41 return (*seed & RAND_MAX);
42}
43DEF_WEAK(rand_r);
44
45#if defined(APIWARN)
46__warn_references(rand_r,
47 "rand_r() is not random, it is deterministic.");
48#endif
49
50int
51rand(void)
52{
53 if (rand_deterministic == 0)
54 return (arc4random() & RAND_MAX);
55 return (rand_r(&next));
56}
57
58#if defined(APIWARN)
59__warn_references(rand,
60 "rand() may return deterministic values, is that what you want?");
61#endif
62
63void
64srand(u_int seed)
65{
66 rand_deterministic = 0;
67}
68
69void
70srand_deterministic(u_int seed)
71{
72 rand_deterministic = 1;
73 next = seed;
74}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
deleted file mode 100644
index fa7a7179bc..0000000000
--- a/src/lib/libc/stdlib/rand48.3
+++ /dev/null
@@ -1,240 +0,0 @@
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.21 2019/12/20 19:16:40 tb Exp $
13.\"
14.Dd $Mdocdate: December 20 2019 $
15.Dt DRAND48 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 srand48_deterministic ,
26.Nm seed48 ,
27.Nm seed48_deterministic ,
28.Nm lcong48 ,
29.Nm lcong48_deterministic
30.Nd pseudo-random number generators and initialization routines
31.Sh SYNOPSIS
32.In stdlib.h
33.Ft double
34.Fn drand48 void
35.Ft double
36.Fn erand48 "unsigned short xseed[3]"
37.Ft long
38.Fn lrand48 void
39.Ft long
40.Fn nrand48 "unsigned short xseed[3]"
41.Ft long
42.Fn mrand48 void
43.Ft long
44.Fn jrand48 "unsigned short xseed[3]"
45.Ft void
46.Fn srand48 "long seed"
47.Ft void
48.Fn srand48_deterministic "long seed"
49.Ft "unsigned short *"
50.Fn seed48 "unsigned short xseed[3]"
51.Ft "unsigned short *"
52.Fn seed48_deterministic "unsigned short xseed[3]"
53.Ft void
54.Fn lcong48 "unsigned short p[7]"
55.Ft void
56.Fn lcong48_deterministic "unsigned short p[7]"
57.Sh DESCRIPTION
58.Bf -symbolic
59Standards insist that this interface return deterministic results.
60Unsafe usage is very common, so
61.Ox
62changed the subsystem to return non-deterministic results by default.
63.Ef
64.Pp
65To satisfy portable code,
66.Fn srand48 ,
67.Fn seed48 ,
68or
69.Fn lcong48
70should be called to initialize the subsystem.
71In
72.Ox
73the
74seeding parameters are ignored, and strong random number results will be
75provided from
76.Xr arc4random 3 .
77In other systems, the
78parameters prime a simplistic deterministic algorithm.
79.Pp
80If the standardized behavior is required then
81.Fn srand48_deterministic ,
82.Fn seed48_deterministic ,
83and
84.Fn lcong48_deterministic
85can be substituted for
86.Fn srand48 ,
87.Fn seed48 ,
88and
89.Fn lcong48 .
90That will cause subsequent
91calls to
92.Fn drand48 ,
93.Fn lrand48 ,
94and
95.Fn jrand48
96to return results using the deterministic algorithm.
97.Pp
98.Fn drand48
99and
100.Fn erand48
101return values of type double.
102The full 48 bits of r(n+1) are
103loaded into the mantissa of the returned value, with the exponent set
104such that the values produced lie in the interval [0.0, 1.0).
105.Pp
106.Fn lrand48
107and
108.Fn nrand48
109return values of type long in the range
110[0, 2**31-1].
111The high-order (31) bits of
112r(n+1) are loaded into the lower bits of the returned value, with
113the topmost (sign) bit set to zero.
114.Pp
115.Fn mrand48
116and
117.Fn jrand48
118return values of type long in the range
119[-2**31, 2**31-1].
120The high-order (32) bits of r(n+1) are loaded into the returned value.
121.Pp
122In the deterministic mode, the
123.Fn rand48
124family of functions generates numbers using a linear congruential
125algorithm working on integers 48 bits in size.
126The particular formula employed is
127r(n+1) = (a * r(n) + c) mod m
128where the default values are
129for the multiplicand a = 0xfdeece66d = 25214903917 and
130the addend c = 0xb = 11.
131The modulus is always fixed at m = 2 ** 48.
132r(n) is called the seed of the random number generator.
133.Pp
134For all the six generator routines described next, the first
135computational step is to perform a single iteration of the algorithm.
136.Pp
137.Fn drand48 ,
138.Fn lrand48 ,
139and
140.Fn mrand48
141use an internal buffer to store r(n).
142For these functions
143the initial value of r(0) = 0x1234abcd330e = 20017429951246.
144.Pp
145On the other hand,
146.Fn erand48 ,
147.Fn nrand48 ,
148and
149.Fn jrand48
150use a user-supplied buffer to store the seed r(n),
151which consists of an array of 3 shorts, where the zeroth member
152holds the least significant bits.
153.Pp
154All functions share the same multiplicand and addend.
155.Pp
156.Fn srand48_deterministic
157is used to initialize the internal buffer r(n) of
158.Fn drand48 ,
159.Fn lrand48 ,
160and
161.Fn mrand48
162such that the 32 bits of the seed value are copied into the upper 32 bits
163of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
164Additionally, the constant multiplicand and addend of the algorithm are
165reset to the default values given above.
166.Pp
167.Fn seed48_deterministic
168also initializes the internal buffer r(n) of
169.Fn drand48 ,
170.Fn lrand48 ,
171and
172.Fn mrand48 ,
173but here all 48 bits of the seed can be specified in an array of 3 shorts,
174where the zeroth member specifies the lowest bits.
175Again, the constant multiplicand and addend of the algorithm are
176reset to the default values given above.
177.Fn seed48_deterministic
178returns a pointer to an array of 3 shorts which contains the old seed.
179This array is statically allocated, so its contents are lost after
180each new call to
181.Fn seed48_deterministic .
182.Pp
183Finally,
184.Fn lcong48_deterministic
185allows full control over the multiplicand and addend used in
186.Fn drand48 ,
187.Fn erand48 ,
188.Fn lrand48 ,
189.Fn nrand48 ,
190.Fn mrand48 ,
191and
192.Fn jrand48 ,
193and the seed used in
194.Fn drand48 ,
195.Fn lrand48 ,
196and
197.Fn mrand48 .
198An array of 7 shorts is passed as parameter; the first three shorts are
199used to initialize the seed; the second three are used to initialize the
200multiplicand; and the last short is used to initialize the addend.
201It is thus not possible to use values greater than 0xffff as the addend.
202.Pp
203Note that all three methods of seeding the random number generator
204always also set the multiplicand and addend for any of the six
205generator calls.
206.Sh SEE ALSO
207.Xr arc4random 3 ,
208.Xr rand 3 ,
209.Xr random 3
210.Sh STANDARDS
211The
212.Fn drand48 ,
213.Fn erand48 ,
214.Fn jrand48 ,
215.Fn lrand48 ,
216.Fn mrand48 ,
217and
218.Fn nrand48 ,
219functions conform to
220.St -p1003.1-2008 .
221.Pp
222The
223.Fn seed48 ,
224.Fn srand48 ,
225and
226.Fn lcong48
227function do not conform to
228.St -ansiC ,
229intentionally.
230.Pp
231The
232.Fn seed48_deterministic ,
233.Fn srand48_deterministic ,
234and
235.Fn lcong48_deterministic
236functions are
237.Ox
238extensions.
239.Sh AUTHORS
240.An Martin Birgmeier
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
deleted file mode 100644
index 7a719beba6..0000000000
--- a/src/lib/libc/stdlib/rand48.h
+++ /dev/null
@@ -1,38 +0,0 @@
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.6 2015/09/14 13:30:17 guenther Exp $
14 */
15
16#ifndef _RAND48_H_
17#define _RAND48_H_
18
19#include <stdlib.h>
20
21__BEGIN_HIDDEN_DECLS
22extern unsigned short __rand48_seed[3];
23extern unsigned short __rand48_mult[3];
24extern unsigned short __rand48_add;
25
26void __dorand48(unsigned short[3]);
27extern int __rand48_deterministic;
28__END_HIDDEN_DECLS
29
30#define RAND48_SEED_0 (0x330e)
31#define RAND48_SEED_1 (0xabcd)
32#define RAND48_SEED_2 (0x1234)
33#define RAND48_MULT_0 (0xe66d)
34#define RAND48_MULT_1 (0xdeec)
35#define RAND48_MULT_2 (0x0005)
36#define RAND48_ADD (0x000b)
37
38#endif /* _RAND48_H_ */
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
deleted file mode 100644
index 0770d20f09..0000000000
--- a/src/lib/libc/stdlib/random.3
+++ /dev/null
@@ -1,197 +0,0 @@
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.29 2021/02/12 17:03:51 deraadt Exp $
29.\"
30.Dd $Mdocdate: February 12 2021 $
31.Dt RANDOM 3
32.Os
33.Sh NAME
34.Nm random ,
35.Nm srandom ,
36.Nm srandom_deterministic ,
37.Nm srandomdev ,
38.Nm initstate ,
39.Nm setstate
40.Nd pseudo-random number generator; routines for changing generators
41.Sh SYNOPSIS
42.In stdlib.h
43.Ft long
44.Fn random void
45.Ft void
46.Fn srandom "unsigned int seed"
47.Ft void
48.Fn srandom_deterministic "unsigned int seed"
49.Ft void
50.Fn srandomdev void
51.Ft char *
52.Fn initstate "unsigned int seed" "char *state" "size_t n"
53.Ft char *
54.Fn setstate "char *state"
55.Sh DESCRIPTION
56.Bf -symbolic
57Standards insist that this interface return deterministic results.
58Unsafe usage is very common, so
59.Ox
60changed the subsystem to return non-deterministic results by default.
61.Ef
62.Pp
63To satisfy portable code,
64.Fn srandom
65or
66.Fn srandomdev
67may be called to initialize the subsystem.
68In
69.Ox
70the
71.Ar seed
72variable is ignored, and strong random number results will be provided from
73.Xr arc4random 3 .
74In other systems, the
75.Ar seed
76variable primes a simplistic deterministic algorithm.
77.Pp
78If the standardized behavior is required
79.Fn srandom_deterministic
80can be substituted for
81.Fn srandom ,
82then subsequent
83.Fn random
84calls will return results using the deterministic algorithm.
85.Pp
86In non-deterministic (default) mode, the
87.Fn random
88function returns results from
89.Xr arc4random 3
90in the range from 0 to (2**31)\-1.
91.Pp
92In deterministic mode, the
93.Fn random
94function uses a non-linear additive feedback random number generator employing
95a default table of size 31 long integers to return successive pseudo-random
96numbers in the range from 0 to (2**31)\-1.
97The period of this random number generator is very large, approximately
9816*((2**31)\-1), but the results are a deterministic sequence from the seed.
99The deterministic sequence algorithm changed a number of times since
100original development, is underspecified, and should not be relied upon to
101remain consistent between platforms and over time.
102.Pp
103The
104.Fn initstate
105routine allows a state array, passed in as an argument, to be initialized
106for future use.
107The size of the state array (in bytes) is used by
108.Fn initstate
109to decide how sophisticated a random number generator it should use \(em the
110more state, the better the random numbers will be.
111(Current "optimal" values for the amount of state information are
1128, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
113the nearest known amount.
114Using less than 8 bytes will cause an error.)
115The seed for the initialization (which specifies a starting point for
116the random number sequence, and provides for restarting at the same
117point) is also an argument.
118The
119.Fn initstate
120function returns a pointer to the previous state information array.
121.Pp
122Once a state has been initialized, the
123.Fn setstate
124routine provides for rapid switching between states.
125The
126.Fn setstate
127function returns a pointer to the previous state array; its
128argument state array is used for further random number generation
129until the next call to
130.Fn initstate
131or
132.Fn setstate .
133.Pp
134Once a state array has been initialized, it may be restarted at a
135different point either by calling
136.Fn initstate
137(with the desired seed, the state array, and its size) or by calling
138both
139.Fn setstate
140(with the state array) and
141.Fn srandom
142(with the desired seed).
143The advantage of calling both
144.Fn setstate
145and
146.Fn srandom
147is that the size of the state array does not have to be remembered after
148it is initialized.
149.Pp
150Use of
151.Fn srandom_deterministic ,
152.Fn initstate ,
153or
154.Fn setstate
155forces the subsystem into deterministic mode.
156.Sh DIAGNOSTICS
157If
158.Fn initstate
159is called with less than 8 bytes of state information, or if
160.Fn setstate
161detects that the state information has been garbled, error
162messages are printed on the standard error output.
163.Sh SEE ALSO
164.Xr arc4random 3 ,
165.Xr drand48 3 ,
166.Xr rand 3 ,
167.Xr random 4
168.Sh STANDARDS
169The
170.Fn random ,
171.Fn initstate ,
172and
173.Fn setstate
174functions conform to
175.St -xpg4.2 .
176.Pp
177The
178.Fn srandom
179function does not conform to
180.St -xpg4.2 ,
181intentionally.
182.Pp
183The
184.Fn srandomdev
185function is an extension.
186.Pp
187The
188.Fn srandom_deterministic
189function is an
190.Ox
191extension.
192.Sh HISTORY
193These
194functions appeared in
195.Bx 4.2 .
196.Sh AUTHORS
197.An Earl T. Cohen
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
deleted file mode 100644
index 62a0c24bdb..0000000000
--- a/src/lib/libc/stdlib/random.c
+++ /dev/null
@@ -1,419 +0,0 @@
1/* $OpenBSD: random.c,v 1.31 2017/11/28 06:55:49 tb 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 <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35
36#include "thread_private.h"
37
38/*
39 * random.c:
40 *
41 * An improved random number generation package. In addition to the standard
42 * rand()/srand() like interface, this package also has a special state info
43 * interface. The initstate() routine is called with a seed, an array of
44 * bytes, and a count of how many bytes are being passed in; this array is
45 * then initialized to contain information for random number generation with
46 * that much state information. Good sizes for the amount of state
47 * information are 32, 64, 128, and 256 bytes. The state can be switched by
48 * calling the setstate() routine with the same array as was initiallized
49 * with initstate(). By default, the package runs with 128 bytes of state
50 * information and generates far better random numbers than a linear
51 * congruential generator. If the amount of state information is less than
52 * 32 bytes, a simple linear congruential R.N.G. is used.
53 *
54 * Internally, the state information is treated as an array of int32_t; the
55 * zeroeth element of the array is the type of R.N.G. being used (small
56 * integer); the remainder of the array is the state information for the
57 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
58 * state information, which will allow a degree seven polynomial. (Note:
59 * the zeroeth word of state information also has some other information
60 * stored in it -- see setstate() for details).
61 *
62 * The random number generation technique is a linear feedback shift register
63 * approach, employing trinomials (since there are fewer terms to sum up that
64 * way). In this approach, the least significant bit of all the numbers in
65 * the state table will act as a linear feedback shift register, and will
66 * have period 2^deg - 1 (where deg is the degree of the polynomial being
67 * used, assuming that the polynomial is irreducible and primitive). The
68 * higher order bits will have longer periods, since their values are also
69 * influenced by pseudo-random carries out of the lower bits. The total
70 * period of the generator is approximately deg*(2**deg - 1); thus doubling
71 * the amount of state information has a vast influence on the period of the
72 * generator. Note: the deg*(2**deg - 1) is an approximation only good for
73 * large deg, when the period of the shift register is the dominant factor.
74 * With deg equal to seven, the period is actually much longer than the
75 * 7*(2**7 - 1) predicted by this formula.
76 */
77
78/*
79 * For each of the currently supported random number generators, we have a
80 * break value on the amount of state information (you need at least this
81 * many bytes of state info to support this random number generator), a degree
82 * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
83 * the separation between the two lower order coefficients of the trinomial.
84 */
85#define TYPE_0 0 /* linear congruential */
86#define BREAK_0 8
87#define DEG_0 0
88#define SEP_0 0
89
90#define TYPE_1 1 /* x**7 + x**3 + 1 */
91#define BREAK_1 32
92#define DEG_1 7
93#define SEP_1 3
94
95#define TYPE_2 2 /* x**15 + x + 1 */
96#define BREAK_2 64
97#define DEG_2 15
98#define SEP_2 1
99
100#define TYPE_3 3 /* x**31 + x**3 + 1 */
101#define BREAK_3 128
102#define DEG_3 31
103#define SEP_3 3
104
105#define TYPE_4 4 /* x**63 + x + 1 */
106#define BREAK_4 256
107#define DEG_4 63
108#define SEP_4 1
109
110/*
111 * Array versions of the above information to make code run faster --
112 * relies on fact that TYPE_i == i.
113 */
114#define MAX_TYPES 5 /* max number of types above */
115
116static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
117static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
118
119/*
120 * Initially, everything is set up as if from:
121 *
122 * initstate(1, &randtbl, 128);
123 *
124 * Note that this initialization takes advantage of the fact that srandom()
125 * advances the front and rear pointers 10*rand_deg times, and hence the
126 * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
127 * element of the state information, which contains info about the current
128 * position of the rear pointer is just
129 *
130 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
131 */
132
133static int32_t randtbl[DEG_3 + 1] = {
134 TYPE_3,
135 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
136 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
137 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
138 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
139 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
140 0xf3bec5da,
141};
142
143/*
144 * fptr and rptr are two pointers into the state info, a front and a rear
145 * pointer. These two pointers are always rand_sep places aparts, as they
146 * cycle cyclically through the state information. (Yes, this does mean we
147 * could get away with just one pointer, but the code for random() is more
148 * efficient this way). The pointers are left positioned as they would be
149 * from the call
150 *
151 * initstate(1, randtbl, 128);
152 *
153 * (The position of the rear pointer, rptr, is really 0 (as explained above
154 * in the initialization of randtbl) because the state table pointer is set
155 * to point to randtbl[1] (as explained below).
156 */
157static int32_t *fptr = &randtbl[SEP_3 + 1];
158static int32_t *rptr = &randtbl[1];
159
160/*
161 * The following things are the pointer to the state information table, the
162 * type of the current generator, the degree of the current polynomial being
163 * used, and the separation between the two pointers. Note that for efficiency
164 * of random(), we remember the first location of the state information, not
165 * the zeroeth. Hence it is valid to access state[-1], which is used to
166 * store the type of the R.N.G. Also, we remember the last location, since
167 * this is more efficient than indexing every time to find the address of
168 * the last element to see if the front and rear pointers have wrapped.
169 */
170static int32_t *state = &randtbl[1];
171static int32_t *end_ptr = &randtbl[DEG_3 + 1];
172static int rand_type = TYPE_3;
173static int rand_deg = DEG_3;
174static int rand_sep = SEP_3;
175
176static int random_deterministic;
177
178static void *random_mutex;
179static long random_l(void);
180
181#define LOCK() _MUTEX_LOCK(&random_mutex)
182#define UNLOCK() _MUTEX_UNLOCK(&random_mutex)
183
184/*
185 * srandom:
186 *
187 * Initialize the random number generator based on the given seed. If the
188 * type is the trivial no-state-information type, just remember the seed.
189 * Otherwise, initializes state[] based on the given "seed" via a linear
190 * congruential generator. Then, the pointers are set to known locations
191 * that are exactly rand_sep places apart. Lastly, it cycles the state
192 * information a given number of times to get rid of any initial dependencies
193 * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
194 * for default usage relies on values produced by this routine.
195 */
196static void
197srandom_l(unsigned int x)
198{
199 int i;
200 int32_t test;
201 div_t val;
202
203 random_deterministic = 1;
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 random_deterministic = 0;
232}
233
234void
235srandomdev(void)
236{
237 random_deterministic = 0; /* back to the default */
238}
239
240void
241srandom_deterministic(unsigned int x)
242{
243 LOCK();
244 srandom_l(x);
245 UNLOCK();
246}
247
248/*
249 * initstate:
250 *
251 * Initialize the state information in the given array of n bytes for future
252 * random number generation. Based on the number of bytes we are given, and
253 * the break values for the different R.N.G.'s, we choose the best (largest)
254 * one we can and set things up for it. srandom() is then called to
255 * initialize the state information.
256 *
257 * Note that on return from srandom(), we set state[-1] to be the type
258 * multiplexed with the current value of the rear pointer; this is so
259 * successive calls to initstate() won't lose this information and will be
260 * able to restart with setstate().
261 *
262 * Note: the first thing we do is save the current state, if any, just like
263 * setstate() so that it doesn't matter when initstate is called.
264 *
265 * Returns a pointer to the old state.
266 */
267char *
268initstate(u_int seed, char *arg_state, size_t n)
269{
270 char *ostate = (char *)(&state[-1]);
271
272 LOCK();
273 random_deterministic = 1;
274 if (rand_type == TYPE_0)
275 state[-1] = rand_type;
276 else
277 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
278 if (n < BREAK_0) {
279 UNLOCK();
280 return(NULL);
281 }
282 if (n < BREAK_1) {
283 rand_type = TYPE_0;
284 rand_deg = DEG_0;
285 rand_sep = SEP_0;
286 } else if (n < BREAK_2) {
287 rand_type = TYPE_1;
288 rand_deg = DEG_1;
289 rand_sep = SEP_1;
290 } else if (n < BREAK_3) {
291 rand_type = TYPE_2;
292 rand_deg = DEG_2;
293 rand_sep = SEP_2;
294 } else if (n < BREAK_4) {
295 rand_type = TYPE_3;
296 rand_deg = DEG_3;
297 rand_sep = SEP_3;
298 } else {
299 rand_type = TYPE_4;
300 rand_deg = DEG_4;
301 rand_sep = SEP_4;
302 }
303 state = &(((int32_t *)arg_state)[1]); /* first location */
304 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
305 srandom_l(seed);
306 if (rand_type == TYPE_0)
307 state[-1] = rand_type;
308 else
309 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
310 UNLOCK();
311 return(ostate);
312}
313
314/*
315 * setstate:
316 *
317 * Restore the state from the given state array.
318 *
319 * Note: it is important that we also remember the locations of the pointers
320 * in the current state information, and restore the locations of the pointers
321 * from the old state information. This is done by multiplexing the pointer
322 * location into the zeroeth word of the state information.
323 *
324 * Note that due to the order in which things are done, it is OK to call
325 * setstate() with the same state as the current state.
326 *
327 * Returns a pointer to the old state information.
328 */
329char *
330setstate(char *arg_state)
331{
332 int32_t *new_state = (int32_t *)arg_state;
333 int32_t type = new_state[0] % MAX_TYPES;
334 int32_t rear = new_state[0] / MAX_TYPES;
335 char *ostate = (char *)(&state[-1]);
336
337 LOCK();
338 random_deterministic = 1;
339 if (rand_type == TYPE_0)
340 state[-1] = rand_type;
341 else
342 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
343 switch(type) {
344 case TYPE_0:
345 case TYPE_1:
346 case TYPE_2:
347 case TYPE_3:
348 case TYPE_4:
349 rand_type = type;
350 rand_deg = degrees[type];
351 rand_sep = seps[type];
352 break;
353 default:
354 UNLOCK();
355 return(NULL);
356 }
357 state = &new_state[1];
358 if (rand_type != TYPE_0) {
359 rptr = &state[rear];
360 fptr = &state[(rear + rand_sep) % rand_deg];
361 }
362 end_ptr = &state[rand_deg]; /* set end_ptr too */
363 UNLOCK();
364 return(ostate);
365}
366
367/*
368 * random:
369 *
370 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
371 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
372 * the same in all the other cases due to all the global variables that have
373 * been set up. The basic operation is to add the number at the rear pointer
374 * into the one at the front pointer. Then both pointers are advanced to
375 * the next location cyclically in the table. The value returned is the sum
376 * generated, reduced to 31 bits by throwing away the "least random" low bit.
377 *
378 * Note: the code takes advantage of the fact that both the front and
379 * rear pointers can't wrap on the same call by not testing the rear
380 * pointer if the front one has wrapped.
381 *
382 * Returns a 31-bit random number.
383 */
384static long
385random_l(void)
386{
387 int32_t i;
388
389 if (random_deterministic == 0)
390 return arc4random() & 0x7fffffff;
391
392 if (rand_type == TYPE_0)
393 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
394 else {
395 *fptr += *rptr;
396 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
397 if (++fptr >= end_ptr) {
398 fptr = state;
399 ++rptr;
400 } else if (++rptr >= end_ptr)
401 rptr = state;
402 }
403 return((long)i);
404}
405
406long
407random(void)
408{
409 long r;
410 LOCK();
411 r = random_l();
412 UNLOCK();
413 return r;
414}
415
416#if defined(APIWARN)
417__warn_references(random,
418 "random() may return deterministic values, is that what you want?");
419#endif
diff --git a/src/lib/libc/stdlib/reallocarray.c b/src/lib/libc/stdlib/reallocarray.c
deleted file mode 100644
index baea252a87..0000000000
--- a/src/lib/libc/stdlib/reallocarray.c
+++ /dev/null
@@ -1,39 +0,0 @@
1/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */
2/*
3 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
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
18#include <sys/types.h>
19#include <errno.h>
20#include <stdint.h>
21#include <stdlib.h>
22
23/*
24 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
25 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
26 */
27#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
28
29void *
30reallocarray(void *optr, size_t nmemb, size_t size)
31{
32 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
33 nmemb > 0 && SIZE_MAX / nmemb < size) {
34 errno = ENOMEM;
35 return NULL;
36 }
37 return realloc(optr, size * nmemb);
38}
39DEF_WEAK(reallocarray);
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
deleted file mode 100644
index 1dec10fef4..0000000000
--- a/src/lib/libc/stdlib/realpath.3
+++ /dev/null
@@ -1,165 +0,0 @@
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.26 2021/10/13 15:04:53 kn Exp $
32.\"
33.Dd $Mdocdate: October 13 2021 $
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 components 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
99will fail if:
100.Bl -tag -width Er
101.It Bq Er EACCES
102Read or search permission was denied for a component of
103.Ar pathname .
104.It Bq Er EINVAL
105The
106.Ar pathname
107argument is a null pointer.
108.It Bq Er EIO
109An error occurred while reading from the file system.
110.It Bq Er ELOOP
111Too many symbolic links were encountered in translating
112.Ar pathname .
113.It Bq Er ENAMETOOLONG
114A component of
115.Ar pathname
116exceeded
117.Dv NAME_MAX
118characters, or the entire
119.Ar pathname
120(including the terminating NUL) exceeded
121.Dv PATH_MAX .
122.It Bq Er ENAMETOOLONG
123Pathname resolution of a symbolic link produced an intermediate
124result whose length exceeds
125.Dv PATH_MAX .
126.It Bq Er ENOENT
127A component of
128.Ar pathname
129does not name an existing file or
130.Ar pathname
131points to an empty string.
132.It Bq Er ENOTDIR
133A component of the path prefix is not a directory.
134.It Bq Er ENOMEM
135Sufficient storage space is unavailable for allocation.
136.El
137.Sh SEE ALSO
138.Xr readlink 1 ,
139.Xr realpath 1 ,
140.Xr getcwd 3
141.Sh STANDARDS
142The
143.Fn realpath
144function conforms to
145.St -p1003.1-2008 .
146.Sh HISTORY
147The
148.Fn realpath
149function call first appeared in
150.Bx 4.4 .
151.Pp
152In
153.Ox 6.6 ,
154it was reimplemented on top of the
155.Fn __realpath
156system call.
157Its calling convention differs from the standard
158function by requiring
159.Ar resolved
160to not be
161.Dv NULL
162and by returning an integer,
163zero on success, and -1 with corresponding errno on failure.
164This is visible in the output of
165.Xr kdump 1 .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
deleted file mode 100644
index 6562e1311b..0000000000
--- a/src/lib/libc/stdlib/realpath.c
+++ /dev/null
@@ -1,42 +0,0 @@
1/* $OpenBSD: realpath.c,v 1.28 2023/05/18 16:11:10 guenther Exp $ */
2/*
3 * Copyright (c) 2019 Bob Beck <beck@openbsd.org>
4 * Copyright (c) 2019 Theo de Raadt <deraadt@openbsd.org>
5 *
6 * Permission to use, copy, modify, and/or 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 ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <limits.h>
24#include <syslog.h>
25#include <stdarg.h>
26
27/*
28 * wrapper for kernel __realpath
29 */
30
31char *
32realpath(const char *path, char *resolved)
33{
34 char rbuf[PATH_MAX];
35
36 if (__realpath(path, rbuf) == -1)
37 return NULL;
38 if (resolved == NULL)
39 return (strdup(rbuf));
40 strlcpy(resolved, rbuf, PATH_MAX);
41 return (resolved);
42}
diff --git a/src/lib/libc/stdlib/recallocarray.c b/src/lib/libc/stdlib/recallocarray.c
deleted file mode 100644
index 81059e6ae1..0000000000
--- a/src/lib/libc/stdlib/recallocarray.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* $OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $ */
2/*
3 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
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
18#include <errno.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <unistd.h>
23
24/*
25 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
26 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
27 */
28#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
29
30void *
31recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
32{
33 size_t oldsize, newsize;
34 void *newptr;
35
36 if (ptr == NULL)
37 return calloc(newnmemb, size);
38
39 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
40 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
41 errno = ENOMEM;
42 return NULL;
43 }
44 newsize = newnmemb * size;
45
46 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
47 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
48 errno = EINVAL;
49 return NULL;
50 }
51 oldsize = oldnmemb * size;
52
53 /*
54 * Don't bother too much if we're shrinking just a bit,
55 * we do not shrink for series of small steps, oh well.
56 */
57 if (newsize <= oldsize) {
58 size_t d = oldsize - newsize;
59
60 if (d < oldsize / 2 && d < (size_t)getpagesize()) {
61 memset((char *)ptr + newsize, 0, d);
62 return ptr;
63 }
64 }
65
66 newptr = malloc(newsize);
67 if (newptr == NULL)
68 return NULL;
69
70 if (newsize > oldsize) {
71 memcpy(newptr, ptr, oldsize);
72 memset((char *)newptr + oldsize, 0, newsize - oldsize);
73 } else
74 memcpy(newptr, ptr, newsize);
75
76 explicit_bzero(ptr, oldsize);
77 free(ptr);
78
79 return newptr;
80}
81DEF_WEAK(recallocarray);
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
deleted file mode 100644
index 71b74b2dce..0000000000
--- a/src/lib/libc/stdlib/remque.c
+++ /dev/null
@@ -1,48 +0,0 @@
1/* $OpenBSD: remque.c,v 1.3 2014/08/15 04:14:36 guenther 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 <stdlib.h>
32#include <search.h>
33
34struct qelem {
35 struct qelem *q_forw;
36 struct qelem *q_back;
37};
38
39void
40remque(void *element)
41{
42 struct qelem *e = element;
43
44 if (e->q_forw != NULL)
45 e->q_forw->q_back = e->q_back;
46 if (e->q_back != NULL)
47 e->q_back->q_forw = e->q_forw;
48}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
deleted file mode 100644
index b4b4424c73..0000000000
--- a/src/lib/libc/stdlib/seed48.c
+++ /dev/null
@@ -1,45 +0,0 @@
1/* $OpenBSD: seed48.c,v 1.6 2015/09/13 15:20:40 guenther 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 *
18seed48(unsigned short xseed[3])
19{
20 unsigned short *res;
21
22 res = seed48_deterministic(xseed);
23 __rand48_deterministic = 0;
24 return res;
25}
26
27unsigned short *
28seed48_deterministic(unsigned short xseed[3])
29{
30 static unsigned short sseed[3];
31
32 __rand48_deterministic = 1;
33 sseed[0] = __rand48_seed[0];
34 sseed[1] = __rand48_seed[1];
35 sseed[2] = __rand48_seed[2];
36 __rand48_seed[0] = xseed[0];
37 __rand48_seed[1] = xseed[1];
38 __rand48_seed[2] = xseed[2];
39 __rand48_mult[0] = RAND48_MULT_0;
40 __rand48_mult[1] = RAND48_MULT_1;
41 __rand48_mult[2] = RAND48_MULT_2;
42 __rand48_add = RAND48_ADD;
43 return sseed;
44}
45DEF_WEAK(seed48_deterministic);
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
deleted file mode 100644
index fc8e5b677f..0000000000
--- a/src/lib/libc/stdlib/setenv.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/* $OpenBSD: setenv.c,v 1.20 2022/08/08 22:40:03 millert 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
35static char **lastenv; /* last value of environ */
36
37/*
38 * putenv --
39 * Add a name=value string directly to the environmental, replacing
40 * any current value.
41 */
42int
43putenv(char *str)
44{
45 char **P, *cp;
46 size_t cnt = 0;
47 int offset = 0;
48
49 for (cp = str; *cp && *cp != '='; ++cp)
50 ;
51 if (cp == str || *cp != '=') {
52 /* '=' is the first character of string or is missing. */
53 errno = EINVAL;
54 return (-1);
55 }
56
57 if (__findenv(str, (int)(cp - str), &offset) != NULL) {
58 environ[offset++] = str;
59 /* could be set multiple times */
60 while (__findenv(str, (int)(cp - str), &offset)) {
61 for (P = &environ[offset];; ++P)
62 if (!(*P = *(P + 1)))
63 break;
64 }
65 return (0);
66 }
67
68 /* create new slot for string */
69 if (environ != NULL) {
70 for (P = environ; *P != NULL; P++)
71 ;
72 cnt = P - environ;
73 }
74 P = reallocarray(lastenv, cnt + 2, sizeof(char *));
75 if (!P)
76 return (-1);
77 if (lastenv != environ && environ != NULL)
78 memcpy(P, environ, cnt * sizeof(char *));
79 lastenv = environ = P;
80 environ[cnt] = str;
81 environ[cnt + 1] = NULL;
82 return (0);
83}
84DEF_WEAK(putenv);
85
86/*
87 * setenv --
88 * Set the value of the environmental variable "name" to be
89 * "value". If rewrite is set, replace any current value.
90 */
91int
92setenv(const char *name, const char *value, int rewrite)
93{
94 char *C, **P;
95 const char *np;
96 int l_value, offset = 0;
97
98 if (!name || !*name) {
99 errno = EINVAL;
100 return (-1);
101 }
102 for (np = name; *np && *np != '='; ++np)
103 ;
104 if (*np) {
105 errno = EINVAL;
106 return (-1); /* has `=' in name */
107 }
108
109 l_value = strlen(value);
110 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
111 int tmpoff = offset + 1;
112 if (!rewrite)
113 return (0);
114#if 0 /* XXX - existing entry may not be writable */
115 if (strlen(C) >= l_value) { /* old larger; copy over */
116 while ((*C++ = *value++))
117 ;
118 return (0);
119 }
120#endif
121 /* could be set multiple times */
122 while (__findenv(name, (int)(np - name), &tmpoff)) {
123 for (P = &environ[tmpoff];; ++P)
124 if (!(*P = *(P + 1)))
125 break;
126 }
127 } else { /* create new slot */
128 size_t cnt = 0;
129
130 if (environ != NULL) {
131 for (P = environ; *P != NULL; P++)
132 ;
133 cnt = P - environ;
134 }
135 P = reallocarray(lastenv, cnt + 2, sizeof(char *));
136 if (!P)
137 return (-1);
138 if (lastenv != environ && environ != NULL)
139 memcpy(P, environ, cnt * sizeof(char *));
140 lastenv = environ = P;
141 offset = cnt;
142 environ[cnt + 1] = NULL;
143 }
144 if (!(environ[offset] = /* name + `=' + value */
145 malloc((int)(np - name) + l_value + 2)))
146 return (-1);
147 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
148 ;
149 for (*C++ = '='; (*C++ = *value++); )
150 ;
151 return (0);
152}
153DEF_WEAK(setenv);
154
155/*
156 * unsetenv(name) --
157 * Delete environmental variable "name".
158 */
159int
160unsetenv(const char *name)
161{
162 char **P;
163 const char *np;
164 int offset = 0;
165
166 if (!name || !*name) {
167 errno = EINVAL;
168 return (-1);
169 }
170 for (np = name; *np && *np != '='; ++np)
171 ;
172 if (*np) {
173 errno = EINVAL;
174 return (-1); /* has `=' in name */
175 }
176
177 /* could be set multiple times */
178 while (__findenv(name, (int)(np - name), &offset)) {
179 for (P = &environ[offset];; ++P)
180 if (!(*P = *(P + 1)))
181 break;
182 }
183 return (0);
184}
185DEF_WEAK(unsetenv);
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
deleted file mode 100644
index d41391d445..0000000000
--- a/src/lib/libc/stdlib/srand48.c
+++ /dev/null
@@ -1,38 +0,0 @@
1/* $OpenBSD: srand48.c,v 1.6 2015/09/13 08:31:48 guenther 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
17int __rand48_deterministic;
18
19void
20srand48(long seed)
21{
22 srand48_deterministic(seed);
23 __rand48_deterministic = 0;
24}
25
26void
27srand48_deterministic(long seed)
28{
29 __rand48_deterministic = 1;
30 __rand48_seed[0] = RAND48_SEED_0;
31 __rand48_seed[1] = (unsigned short) seed;
32 __rand48_seed[2] = (unsigned short) (seed >> 16);
33 __rand48_mult[0] = RAND48_MULT_0;
34 __rand48_mult[1] = RAND48_MULT_1;
35 __rand48_mult[2] = RAND48_MULT_2;
36 __rand48_add = RAND48_ADD;
37}
38DEF_WEAK(srand48_deterministic);
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
deleted file mode 100644
index ad8f28a02f..0000000000
--- a/src/lib/libc/stdlib/strtod.3
+++ /dev/null
@@ -1,176 +0,0 @@
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.23 2022/09/11 06:38:11 jmc Exp $
33.\"
34.Dd $Mdocdate: September 11 2022 $
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.Vt double
59representation.
60The
61.Fn strtof
62function converts the initial portion of the string pointed to by
63.Fa nptr
64to
65.Vt float
66representation.
67The
68.Fn strtold
69function converts the initial portion of the string pointed to by
70.Fa nptr
71to
72.Vt 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 -isoC-99 .
168.Sh CAVEATS
169On systems other than
170.Ox ,
171the
172.Dv LC_NUMERIC
173.Xr locale 1
174category can cause parsing failures; see CAVEATS in
175.Xr setlocale 3
176for details.
diff --git a/src/lib/libc/stdlib/strtoimax.c b/src/lib/libc/stdlib/strtoimax.c
deleted file mode 100644
index 74e355626a..0000000000
--- a/src/lib/libc/stdlib/strtoimax.c
+++ /dev/null
@@ -1,151 +0,0 @@
1/* $OpenBSD: strtoimax.c,v 1.4 2017/07/06 16:23:11 millert 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 <ctype.h>
32#include <errno.h>
33#include <inttypes.h>
34
35/*
36 * Convert a string to an intmax_t
37 *
38 * Ignores `locale' stuff. Assumes that the upper and lower case
39 * alphabets and digits are each contiguous.
40 */
41intmax_t
42strtoimax(const char *nptr, char **endptr, int base)
43{
44 const char *s;
45 intmax_t acc, cutoff;
46 int c;
47 int neg, any, cutlim;
48
49 /*
50 * Ensure that base is between 2 and 36 inclusive, or the special
51 * value of 0.
52 */
53 if (base < 0 || base == 1 || base > 36) {
54 if (endptr != 0)
55 *endptr = (char *)nptr;
56 errno = EINVAL;
57 return 0;
58 }
59
60 /*
61 * Skip white space and pick up leading +/- sign if any.
62 * If base is 0, allow 0x for hex and 0 for octal, else
63 * assume decimal; if base is already 16, allow 0x.
64 */
65 s = nptr;
66 do {
67 c = (unsigned char) *s++;
68 } while (isspace(c));
69 if (c == '-') {
70 neg = 1;
71 c = *s++;
72 } else {
73 neg = 0;
74 if (c == '+')
75 c = *s++;
76 }
77 if ((base == 0 || base == 16) && c == '0' &&
78 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
79 c = s[1];
80 s += 2;
81 base = 16;
82 }
83 if (base == 0)
84 base = c == '0' ? 8 : 10;
85
86 /*
87 * Compute the cutoff value between legal numbers and illegal
88 * numbers. That is the largest legal value, divided by the
89 * base. An input number that is greater than this value, if
90 * followed by a legal input character, is too big. One that
91 * is equal to this value may be valid or not; the limit
92 * between valid and invalid numbers is then based on the last
93 * digit. For instance, if the range for intmax_t is
94 * [-9223372036854775808..9223372036854775807] and the input base
95 * is 10, cutoff will be set to 922337203685477580 and cutlim to
96 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
97 * accumulated a value > 922337203685477580, or equal but the
98 * next digit is > 7 (or 8), the number is too big, and we will
99 * return a range error.
100 *
101 * Set any if any `digits' consumed; make it negative to indicate
102 * overflow.
103 */
104 cutoff = neg ? INTMAX_MIN : INTMAX_MAX;
105 cutlim = cutoff % base;
106 cutoff /= base;
107 if (neg) {
108 if (cutlim > 0) {
109 cutlim -= base;
110 cutoff += 1;
111 }
112 cutlim = -cutlim;
113 }
114 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
115 if (isdigit(c))
116 c -= '0';
117 else if (isalpha(c))
118 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
119 else
120 break;
121 if (c >= base)
122 break;
123 if (any < 0)
124 continue;
125 if (neg) {
126 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
127 any = -1;
128 acc = INTMAX_MIN;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc -= c;
134 }
135 } else {
136 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
137 any = -1;
138 acc = INTMAX_MAX;
139 errno = ERANGE;
140 } else {
141 any = 1;
142 acc *= base;
143 acc += c;
144 }
145 }
146 }
147 if (endptr != 0)
148 *endptr = (char *) (any ? s - 1 : nptr);
149 return (acc);
150}
151DEF_STRONG(strtoimax);
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
deleted file mode 100644
index 92774d082c..0000000000
--- a/src/lib/libc/stdlib/strtol.3
+++ /dev/null
@@ -1,273 +0,0 @@
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.27 2015/04/14 22:16:03 nicm Exp $
33.\"
34.Dd $Mdocdate: April 14 2015 $
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.Ft long long
49.Fn strtoll "const char *nptr" "char **endptr" "int base"
50.In inttypes.h
51.Ft intmax_t
52.Fn strtoimax "const char *nptr" "char **endptr" "int base"
53.In sys/types.h
54.In limits.h
55.In stdlib.h
56.Ft quad_t
57.Fn strtoq "const char *nptr" "char **endptr" "int base"
58.Sh DESCRIPTION
59The
60.Fn strtol
61function converts the string in
62.Fa nptr
63to a
64.Vt long
65value.
66The
67.Fn strtoll
68function converts the string in
69.Fa nptr
70to a
71.Vt long long
72value.
73The
74.Fn strtoimax
75function converts the string in
76.Fa nptr
77to an
78.Vt intmax_t
79value.
80The
81.Fn strtoq
82function is a deprecated equivalent of
83.Fn strtoll
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 or the special value 0.
88.Pp
89The string may begin with an arbitrary amount of whitespace
90(as determined by
91.Xr isspace 3 )
92followed by a single optional
93.Ql +
94or
95.Ql -
96sign.
97If
98.Fa base
99is zero or 16, the string may then include a
100.Ql 0x
101prefix, and the number will be read in base 16; otherwise, a zero
102.Fa base
103is taken as 10 (decimal) unless the next character is
104.Ql 0 ,
105in which case it is taken as 8 (octal).
106.Pp
107The remainder of the string is converted to a
108.Vt long ,
109.Vt long long ,
110or
111.Vt intmax_t
112value in the obvious manner,
113stopping at the first character which is not a valid digit
114in the given base.
115(In bases above 10, the letter
116.Ql A
117in either upper or lower case represents 10,
118.Ql B
119represents 11, and so forth, with
120.Ql Z
121representing 35.)
122.Pp
123If
124.Fa endptr
125is non-null,
126.Fn strtol
127stores the address of the first invalid character in
128.Fa *endptr .
129If there were no digits at all, however,
130.Fn strtol
131stores the original value of
132.Fa nptr
133in
134.Fa *endptr .
135(Thus, if
136.Fa *nptr
137is not
138.Ql \e0
139but
140.Fa **endptr
141is
142.Ql \e0
143on return, the entire string was valid.)
144.Sh RETURN VALUES
145The
146.Fn strtol ,
147.Fn strtoll ,
148.Fn strtoimax ,
149and
150.Fn strtoq
151functions return the result of the conversion.
152If overflow or underflow occurs,
153.Va errno
154is set to
155.Er ERANGE
156and the function return value is as follows:
157.Bl -column "strtoimaxXX" "INTMAX_MIN" "INTMAX_MAX" -offset indent
158.It Sy Function Ta Sy underflow Ta Sy overflow
159.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
160.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
161.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
162.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX
163.El
164.Pp
165If there is no valid digit, 0 is returned.
166If
167.Ar base
168is invalid, 0 is returned and the global variable
169.Va errno
170is set to
171.Er EINVAL .
172.Sh EXAMPLES
173Ensuring that a string is a valid number (i.e., in range and containing no
174trailing characters) requires clearing
175.Va errno
176beforehand explicitly since
177.Va errno
178is not changed on a successful call to
179.Fn strtol ,
180and the return value of
181.Fn strtol
182cannot be used unambiguously to signal an error:
183.Bd -literal -offset indent
184char *ep;
185long lval;
186
187\&...
188
189errno = 0;
190lval = strtol(buf, &ep, 10);
191if (buf[0] == '\e0' || *ep != '\e0')
192 goto not_a_number;
193if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
194 goto out_of_range;
195.Ed
196.Pp
197This example will accept
198.Dq 12
199but not
200.Dq 12foo
201or
202.Dq 12\en .
203If trailing whitespace is acceptable, further checks must be done on
204.Va *ep ;
205alternately, use
206.Xr sscanf 3 .
207.Pp
208If
209.Fn strtol
210is being used instead of
211.Xr atoi 3 ,
212error checking is further complicated because the desired return value is an
213.Vt int
214rather than a
215.Vt long ;
216however, on some architectures integers and long integers are the same size.
217Thus the following is necessary:
218.Bd -literal -offset indent
219char *ep;
220int ival;
221long lval;
222
223\&...
224
225errno = 0;
226lval = strtol(buf, &ep, 10);
227if (buf[0] == '\e0' || *ep != '\e0')
228 goto not_a_number;
229if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
230 (lval > INT_MAX || lval < INT_MIN))
231 goto out_of_range;
232ival = lval;
233.Ed
234.Sh ERRORS
235.Bl -tag -width Er
236.It Bq Er EINVAL
237The value of
238.Ar base
239was neither between 2 and 36 inclusive nor the special value 0.
240.It Bq Er ERANGE
241The given string was out of range; the value converted has been clamped.
242.El
243.Sh SEE ALSO
244.Xr atof 3 ,
245.Xr atoi 3 ,
246.Xr atol 3 ,
247.Xr atoll 3 ,
248.Xr sscanf 3 ,
249.Xr strtod 3 ,
250.Xr strtonum 3 ,
251.Xr strtoul 3
252.Sh STANDARDS
253The
254.Fn strtol ,
255.Fn strtoll ,
256and
257.Fn strtoimax
258functions conform to
259.St -isoC-99 .
260Setting
261.Va errno
262to
263.Dv EINVAL
264is an extension to that standard required by
265.St -p1003.1-2008 .
266.Pp
267The
268.Fn strtoq
269function is a
270.Bx
271extension and is provided for backwards compatibility with legacy programs.
272.Sh BUGS
273Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
deleted file mode 100644
index 599d2355a8..0000000000
--- a/src/lib/libc/stdlib/strtol.c
+++ /dev/null
@@ -1,151 +0,0 @@
1/* $OpenBSD: strtol.c,v 1.12 2017/07/06 16:23:11 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 <ctype.h>
32#include <errno.h>
33#include <limits.h>
34#include <stdlib.h>
35
36/*
37 * Convert a string to a long integer.
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42long
43strtol(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 long acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * Ensure that base is between 2 and 36 inclusive, or the special
52 * value of 0.
53 */
54 if (base < 0 || base == 1 || base > 36) {
55 if (endptr != 0)
56 *endptr = (char *)nptr;
57 errno = EINVAL;
58 return 0;
59 }
60
61 /*
62 * Skip white space and pick up leading +/- sign if any.
63 * If base is 0, allow 0x for hex and 0 for octal, else
64 * assume decimal; if base is already 16, allow 0x.
65 */
66 s = nptr;
67 do {
68 c = (unsigned char) *s++;
69 } while (isspace(c));
70 if (c == '-') {
71 neg = 1;
72 c = *s++;
73 } else {
74 neg = 0;
75 if (c == '+')
76 c = *s++;
77 }
78 if ((base == 0 || base == 16) && c == '0' &&
79 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
80 c = s[1];
81 s += 2;
82 base = 16;
83 }
84 if (base == 0)
85 base = c == '0' ? 8 : 10;
86
87 /*
88 * Compute the cutoff value between legal numbers and illegal
89 * numbers. That is the largest legal value, divided by the
90 * base. An input number that is greater than this value, if
91 * followed by a legal input character, is too big. One that
92 * is equal to this value may be valid or not; the limit
93 * between valid and invalid numbers is then based on the last
94 * digit. For instance, if the range for longs is
95 * [-2147483648..2147483647] and the input base is 10,
96 * cutoff will be set to 214748364 and cutlim to either
97 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
98 * a value > 214748364, or equal but the next digit is > 7 (or 8),
99 * the number is too big, and we will return a range error.
100 *
101 * Set any if any `digits' consumed; make it negative to indicate
102 * overflow.
103 */
104 cutoff = neg ? LONG_MIN : LONG_MAX;
105 cutlim = cutoff % base;
106 cutoff /= base;
107 if (neg) {
108 if (cutlim > 0) {
109 cutlim -= base;
110 cutoff += 1;
111 }
112 cutlim = -cutlim;
113 }
114 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
115 if (isdigit(c))
116 c -= '0';
117 else if (isalpha(c))
118 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
119 else
120 break;
121 if (c >= base)
122 break;
123 if (any < 0)
124 continue;
125 if (neg) {
126 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
127 any = -1;
128 acc = LONG_MIN;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc -= c;
134 }
135 } else {
136 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
137 any = -1;
138 acc = LONG_MAX;
139 errno = ERANGE;
140 } else {
141 any = 1;
142 acc *= base;
143 acc += c;
144 }
145 }
146 }
147 if (endptr != 0)
148 *endptr = (char *) (any ? s - 1 : nptr);
149 return (acc);
150}
151DEF_STRONG(strtol);
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
deleted file mode 100644
index d21a249a0b..0000000000
--- a/src/lib/libc/stdlib/strtoll.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/* $OpenBSD: strtoll.c,v 1.10 2017/07/06 16:23:11 millert 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 * Ensure that base is between 2 and 36 inclusive, or the special
54 * value of 0.
55 */
56 if (base < 0 || base == 1 || base > 36) {
57 if (endptr != 0)
58 *endptr = (char *)nptr;
59 errno = EINVAL;
60 return 0;
61 }
62
63 /*
64 * Skip white space and pick up leading +/- sign if any.
65 * If base is 0, allow 0x for hex and 0 for octal, else
66 * assume decimal; if base is already 16, allow 0x.
67 */
68 s = nptr;
69 do {
70 c = (unsigned char) *s++;
71 } while (isspace(c));
72 if (c == '-') {
73 neg = 1;
74 c = *s++;
75 } else {
76 neg = 0;
77 if (c == '+')
78 c = *s++;
79 }
80 if ((base == 0 || base == 16) && c == '0' &&
81 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
82 c = s[1];
83 s += 2;
84 base = 16;
85 }
86 if (base == 0)
87 base = c == '0' ? 8 : 10;
88
89 /*
90 * Compute the cutoff value between legal numbers and illegal
91 * numbers. That is the largest legal value, divided by the
92 * base. An input number that is greater than this value, if
93 * followed by a legal input character, is too big. One that
94 * is equal to this value may be valid or not; the limit
95 * between valid and invalid numbers is then based on the last
96 * digit. For instance, if the range for long longs is
97 * [-9223372036854775808..9223372036854775807] and the input base
98 * is 10, cutoff will be set to 922337203685477580 and cutlim to
99 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
100 * accumulated a value > 922337203685477580, or equal but the
101 * next digit is > 7 (or 8), the number is too big, and we will
102 * return a range error.
103 *
104 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow.
106 */
107 cutoff = neg ? LLONG_MIN : LLONG_MAX;
108 cutlim = cutoff % base;
109 cutoff /= base;
110 if (neg) {
111 if (cutlim > 0) {
112 cutlim -= base;
113 cutoff += 1;
114 }
115 cutlim = -cutlim;
116 }
117 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
118 if (isdigit(c))
119 c -= '0';
120 else if (isalpha(c))
121 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
122 else
123 break;
124 if (c >= base)
125 break;
126 if (any < 0)
127 continue;
128 if (neg) {
129 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
130 any = -1;
131 acc = LLONG_MIN;
132 errno = ERANGE;
133 } else {
134 any = 1;
135 acc *= base;
136 acc -= c;
137 }
138 } else {
139 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
140 any = -1;
141 acc = LLONG_MAX;
142 errno = ERANGE;
143 } else {
144 any = 1;
145 acc *= base;
146 acc += c;
147 }
148 }
149 }
150 if (endptr != 0)
151 *endptr = (char *) (any ? s - 1 : nptr);
152 return (acc);
153}
154DEF_STRONG(strtoll);
155
156__weak_alias(strtoq, strtoll);
diff --git a/src/lib/libc/stdlib/strtonum.3 b/src/lib/libc/stdlib/strtonum.3
deleted file mode 100644
index 87a3ccd588..0000000000
--- a/src/lib/libc/stdlib/strtonum.3
+++ /dev/null
@@ -1,152 +0,0 @@
1.\" $OpenBSD: strtonum.3,v 1.19 2022/09/11 06:38:11 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: September 11 2022 $
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.Vt 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.Vt 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 != NULL)
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
deleted file mode 100644
index ad22d1c30c..0000000000
--- a/src/lib/libc/stdlib/strtonum.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* $OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther 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}
66DEF_WEAK(strtonum);
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
deleted file mode 100644
index dd5668d1d6..0000000000
--- a/src/lib/libc/stdlib/strtoul.3
+++ /dev/null
@@ -1,260 +0,0 @@
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.24 2014/11/30 21:21:59 schwarze Exp $
33.\"
34.Dd $Mdocdate: November 30 2014 $
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.Vt unsigned long
65value.
66The
67.Fn strtoull
68function converts the string in
69.Fa nptr
70to an
71.Vt unsigned long long
72value.
73The
74.Fn strtoumax
75function converts the string in
76.Fa nptr
77to a
78.Vt 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 or the special value 0.
88If the string in
89.Fa nptr
90represents a negative number, it will be converted to its unsigned equivalent.
91This behavior is consistent with what happens when a signed integer type is
92cast to its unsigned counterpart.
93.Pp
94The string may begin with an arbitrary amount of whitespace
95(as determined by
96.Xr isspace 3 )
97followed by a single optional
98.Ql +
99or
100.Ql -
101sign.
102If
103.Fa base
104is zero or 16, the string may then include a
105.Ql 0x
106prefix, and the number will be read in base 16; otherwise, a zero
107.Fa base
108is taken as 10 (decimal) unless the next character is
109.Ql 0 ,
110in which case it is taken as 8 (octal).
111.Pp
112The remainder of the string is converted to an
113.Vt unsigned long ,
114.Vt unsigned long long ,
115or
116.Vt uintmax_t
117value in the obvious manner,
118stopping at the first character which is not a valid digit
119in the given base.
120(In bases above 10, the letter
121.Ql A
122in either upper or lower case represents 10,
123.Ql B
124represents 11, and so forth, with
125.Ql Z
126representing 35.)
127.Pp
128If
129.Fa endptr
130is non-null,
131.Fn strtoul
132stores the address of the first invalid character in
133.Fa *endptr .
134If there were no digits at all, however,
135.Fn strtoul
136stores the original value of
137.Fa nptr
138in
139.Fa *endptr .
140(Thus, if
141.Fa *nptr
142is not
143.Ql \e0
144but
145.Fa **endptr
146is
147.Ql \e0
148on return, the entire string was valid.)
149.Sh RETURN VALUES
150The
151.Fn strtoul ,
152.Fn strtoull ,
153.Fn strtoumax
154and
155.Fn strtouq
156functions return either the result of the conversion or,
157if there was a leading minus sign,
158the negation of the result of the conversion,
159unless the original (non-negated) value would overflow.
160If overflow occurs,
161.Fn strtoul
162returns
163.Dv ULONG_MAX ,
164.Fn strtoull
165returns
166.Dv ULLONG_MAX ,
167.Fn strtoumax
168returns
169.Dv UINTMAX_MAX ,
170.Fn strtouq
171returns
172.Dv ULLONG_MAX
173and the global variable
174.Va errno
175is set to
176.Er ERANGE .
177.Pp
178There is no way to determine if
179.Fn strtoul
180has processed a negative number (and returned an unsigned value) short of
181examining the string in
182.Fa nptr
183directly.
184.Pp
185If there is no valid digit, 0 is returned.
186If
187.Ar base
188is invalid, 0 is returned and the global variable
189.Va errno
190is set to
191.Er EINVAL .
192.Sh EXAMPLES
193Ensuring that a string is a valid number (i.e., in range and containing no
194trailing characters) requires clearing
195.Va errno
196beforehand explicitly since
197.Va errno
198is not changed on a successful call to
199.Fn strtoul ,
200and the return value of
201.Fn strtoul
202cannot be used unambiguously to signal an error:
203.Bd -literal -offset indent
204char *ep;
205unsigned long ulval;
206
207\&...
208
209errno = 0;
210ulval = strtoul(buf, &ep, 10);
211if (buf[0] == '\e0' || *ep != '\e0')
212 goto not_a_number;
213if (errno == ERANGE && ulval == ULONG_MAX)
214 goto out_of_range;
215.Ed
216.Pp
217This example will accept
218.Dq 12
219but not
220.Dq 12foo
221or
222.Dq 12\en .
223If trailing whitespace is acceptable, further checks must be done on
224.Va *ep ;
225alternately, use
226.Xr sscanf 3 .
227.Sh ERRORS
228.Bl -tag -width Er
229.It Bq Er EINVAL
230The value of
231.Ar base
232was neither between 2 and 36 inclusive nor the special value 0.
233.It Bq Er ERANGE
234The given string was out of range; the value converted has been clamped.
235.El
236.Sh SEE ALSO
237.Xr sscanf 3 ,
238.Xr strtol 3
239.Sh STANDARDS
240The
241.Fn strtoul ,
242.Fn strtoull ,
243and
244.Fn strtoumax
245functions conform to
246.St -isoC-99 .
247Setting
248.Va errno
249to
250.Dv EINVAL
251is an extension to that standard required by
252.St -p1003.1-2008 .
253.Pp
254The
255.Fn strtouq
256function is a
257.Bx
258extension and is provided for backwards compatibility with legacy programs.
259.Sh BUGS
260Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
deleted file mode 100644
index 6667bea8fa..0000000000
--- a/src/lib/libc/stdlib/strtoul.c
+++ /dev/null
@@ -1,110 +0,0 @@
1/* $OpenBSD: strtoul.c,v 1.11 2017/07/06 16:23:11 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 <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 if (base < 0 || base == 1 || base > 36) {
54 if (endptr != 0)
55 *endptr = (char *)nptr;
56 errno = EINVAL;
57 return 0;
58 }
59
60 s = nptr;
61 do {
62 c = (unsigned char) *s++;
63 } while (isspace(c));
64 if (c == '-') {
65 neg = 1;
66 c = *s++;
67 } else {
68 neg = 0;
69 if (c == '+')
70 c = *s++;
71 }
72 if ((base == 0 || base == 16) && c == '0' &&
73 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
74 c = s[1];
75 s += 2;
76 base = 16;
77 }
78 if (base == 0)
79 base = c == '0' ? 8 : 10;
80
81 cutoff = ULONG_MAX / (unsigned long)base;
82 cutlim = ULONG_MAX % (unsigned long)base;
83 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
84 if (isdigit(c))
85 c -= '0';
86 else if (isalpha(c))
87 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
88 else
89 break;
90 if (c >= base)
91 break;
92 if (any < 0)
93 continue;
94 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
95 any = -1;
96 acc = ULONG_MAX;
97 errno = ERANGE;
98 } else {
99 any = 1;
100 acc *= (unsigned long)base;
101 acc += c;
102 }
103 }
104 if (neg && any > 0)
105 acc = -acc;
106 if (endptr != 0)
107 *endptr = (char *) (any ? s - 1 : nptr);
108 return (acc);
109}
110DEF_STRONG(strtoul);
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
deleted file mode 100644
index d7733e4003..0000000000
--- a/src/lib/libc/stdlib/strtoull.c
+++ /dev/null
@@ -1,114 +0,0 @@
1/* $OpenBSD: strtoull.c,v 1.9 2017/07/06 16:23:11 millert 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 strtoll for comments as to the logic used.
54 */
55 if (base < 0 || base == 1 || base > 36) {
56 if (endptr != 0)
57 *endptr = (char *)nptr;
58 errno = EINVAL;
59 return 0;
60 }
61
62 s = nptr;
63 do {
64 c = (unsigned char) *s++;
65 } while (isspace(c));
66 if (c == '-') {
67 neg = 1;
68 c = *s++;
69 } else {
70 neg = 0;
71 if (c == '+')
72 c = *s++;
73 }
74 if ((base == 0 || base == 16) && c == '0' &&
75 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
76 c = s[1];
77 s += 2;
78 base = 16;
79 }
80 if (base == 0)
81 base = c == '0' ? 8 : 10;
82
83 cutoff = ULLONG_MAX / (unsigned long long)base;
84 cutlim = ULLONG_MAX % (unsigned long long)base;
85 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
86 if (isdigit(c))
87 c -= '0';
88 else if (isalpha(c))
89 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
90 else
91 break;
92 if (c >= base)
93 break;
94 if (any < 0)
95 continue;
96 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
97 any = -1;
98 acc = ULLONG_MAX;
99 errno = ERANGE;
100 } else {
101 any = 1;
102 acc *= (unsigned long long)base;
103 acc += c;
104 }
105 }
106 if (neg && any > 0)
107 acc = -acc;
108 if (endptr != 0)
109 *endptr = (char *) (any ? s - 1 : nptr);
110 return (acc);
111}
112DEF_STRONG(strtoull);
113
114__weak_alias(strtouq, strtoull);
diff --git a/src/lib/libc/stdlib/strtoumax.c b/src/lib/libc/stdlib/strtoumax.c
deleted file mode 100644
index 348184c1ac..0000000000
--- a/src/lib/libc/stdlib/strtoumax.c
+++ /dev/null
@@ -1,109 +0,0 @@
1/* $OpenBSD: strtoumax.c,v 1.4 2017/07/06 16:23:11 millert 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 <ctype.h>
32#include <errno.h>
33#include <inttypes.h>
34
35/*
36 * Convert a string to a uintmax_t.
37 *
38 * Ignores `locale' stuff. Assumes that the upper and lower case
39 * alphabets and digits are each contiguous.
40 */
41uintmax_t
42strtoumax(const char *nptr, char **endptr, int base)
43{
44 const char *s;
45 uintmax_t acc, cutoff;
46 int c;
47 int neg, any, cutlim;
48
49 /*
50 * See strtoimax for comments as to the logic used.
51 */
52 if (base < 0 || base == 1 || base > 36) {
53 if (endptr != 0)
54 *endptr = (char *)nptr;
55 errno = EINVAL;
56 return 0;
57 }
58
59 s = nptr;
60 do {
61 c = (unsigned char) *s++;
62 } while (isspace(c));
63 if (c == '-') {
64 neg = 1;
65 c = *s++;
66 } else {
67 neg = 0;
68 if (c == '+')
69 c = *s++;
70 }
71 if ((base == 0 || base == 16) && c == '0' &&
72 (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
73 c = s[1];
74 s += 2;
75 base = 16;
76 }
77 if (base == 0)
78 base = c == '0' ? 8 : 10;
79
80 cutoff = UINTMAX_MAX / (uintmax_t)base;
81 cutlim = UINTMAX_MAX % (uintmax_t)base;
82 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
83 if (isdigit(c))
84 c -= '0';
85 else if (isalpha(c))
86 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
87 else
88 break;
89 if (c >= base)
90 break;
91 if (any < 0)
92 continue;
93 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
94 any = -1;
95 acc = UINTMAX_MAX;
96 errno = ERANGE;
97 } else {
98 any = 1;
99 acc *= (uintmax_t)base;
100 acc += c;
101 }
102 }
103 if (neg && any > 0)
104 acc = -acc;
105 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr);
107 return (acc);
108}
109DEF_STRONG(strtoumax);
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
deleted file mode 100644
index bdd94c0115..0000000000
--- a/src/lib/libc/stdlib/system.3
+++ /dev/null
@@ -1,116 +0,0 @@
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.14 2016/02/05 18:09:19 espie Exp $
33.\"
34.Dd $Mdocdate: February 5 2016 $
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.
110.Pp
111It is often simpler to bypass the shell and run an external command using
112.Xr fork 2 ,
113.Xr execlp 3 ,
114and
115.Xr waitpid 2
116directly instead of having to sanitize a string for shell consumption.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
deleted file mode 100644
index 28f01a9c5d..0000000000
--- a/src/lib/libc/stdlib/system.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/* $OpenBSD: system.c,v 1.13 2022/05/21 00:53:53 millert 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 <errno.h>
34#include <signal.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38#include <paths.h>
39
40int
41system(const char *command)
42{
43 pid_t pid, cpid;
44 struct sigaction intsave, quitsave, sa;
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 sigaddset(&mask, SIGINT);
57 sigaddset(&mask, SIGQUIT);
58 sigprocmask(SIG_BLOCK, &mask, &omask);
59 switch (cpid = vfork()) {
60 case -1: /* error */
61 sigprocmask(SIG_SETMASK, &omask, NULL);
62 return(-1);
63 case 0: /* child */
64 sigprocmask(SIG_SETMASK, &omask, NULL);
65 execve(_PATH_BSHELL, argp, environ);
66 _exit(127);
67 }
68
69 /* Ignore SIGINT and SIGQUIT while waiting for command to complete. */
70 memset(&sa, 0, sizeof(sa));
71 sigemptyset(&sa.sa_mask);
72 sa.sa_handler = SIG_IGN;
73 sigaction(SIGINT, &sa, &intsave);
74 sigaction(SIGQUIT, &sa, &quitsave);
75 sigemptyset(&mask);
76 sigaddset(&mask, SIGINT);
77 sigaddset(&mask, SIGQUIT);
78 sigprocmask(SIG_UNBLOCK, &mask, NULL);
79
80 do {
81 pid = waitpid(cpid, &pstat, 0);
82 } while (pid == -1 && errno == EINTR);
83
84 sigprocmask(SIG_SETMASK, &omask, NULL);
85 sigaction(SIGINT, &intsave, NULL);
86 sigaction(SIGQUIT, &quitsave, NULL);
87 return (pid == -1 ? -1 : pstat);
88}
89DEF_STRONG(system);
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
deleted file mode 100644
index 49f9dbc17a..0000000000
--- a/src/lib/libc/stdlib/tfind.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/* $OpenBSD: tfind.c,v 1.7 2015/09/26 16:03:48 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#include <search.h>
14
15typedef struct node_t
16{
17 char *key;
18 struct node_t *llink, *rlink;
19} node;
20
21/* find a node, or return 0 */
22void *
23tfind(const void *vkey, void * const *vrootp,
24 int (*compar)(const void *, const void *))
25{
26 char *key = (char *)vkey;
27 node **rootp = (node **)vrootp;
28
29 if (rootp == (struct node_t **)0)
30 return ((struct node_t *)0);
31 while (*rootp != (struct node_t *)0) { /* T1: */
32 int r;
33 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
34 return (*rootp); /* key found */
35 rootp = (r < 0) ?
36 &(*rootp)->llink : /* T3: follow left branch */
37 &(*rootp)->rlink; /* T4: follow right branch */
38 }
39 return (node *)0;
40}
diff --git a/src/lib/libc/stdlib/thread_atexit.c b/src/lib/libc/stdlib/thread_atexit.c
deleted file mode 100644
index ef0423c428..0000000000
--- a/src/lib/libc/stdlib/thread_atexit.c
+++ /dev/null
@@ -1,44 +0,0 @@
1/* $OpenBSD: thread_atexit.c,v 1.2 2019/06/02 01:03:01 guenther Exp $ */
2/*
3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
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
18#include <dlfcn.h>
19#include <stdlib.h>
20#include <tib.h>
21
22#include "atexit.h"
23
24__weak_alias(__cxa_thread_atexit, __cxa_thread_atexit_impl);
25
26int
27__cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso)
28{
29 struct thread_atexit_fn *fnp;
30 struct tib *tib = TIB_GET();
31
32 fnp = calloc(1, sizeof(struct thread_atexit_fn));
33 if (fnp == NULL)
34 return -1;
35
36 dlctl(NULL, DL_REFERENCE, dso);
37
38 fnp->func = func;
39 fnp->arg = arg;
40 fnp->next = tib->tib_atexit;
41 tib->tib_atexit = fnp;
42
43 return 0;
44}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
deleted file mode 100644
index a7ab985013..0000000000
--- a/src/lib/libc/stdlib/tsearch.3
+++ /dev/null
@@ -1,126 +0,0 @@
1.\" $OpenBSD: tsearch.3,v 1.22 2022/03/31 17:27:16 naddy Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
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: March 31 2022 $
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.Sh SEE ALSO
115.Xr bsearch 3 ,
116.Xr lsearch 3
117.Sh STANDARDS
118These functions conform to
119.St -p1003.1-2008 .
120.Sh CAVEATS
121The value returned when deleting the root node was unspecified before
122the
123.St -p1003.1-2008
124standard, so users of the
125.Fn tdelete
126function 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
deleted file mode 100644
index 1dd31454eb..0000000000
--- a/src/lib/libc/stdlib/tsearch.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/* $OpenBSD: tsearch.c,v 1.10 2015/09/26 16:03:48 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
14#include <search.h>
15#include <stdlib.h>
16
17typedef struct node_t {
18 char *key;
19 struct node_t *left, *right;
20} node;
21
22/* find or insert datum into search tree */
23void *
24tsearch(const void *vkey, void **vrootp,
25 int (*compar)(const void *, const void *))
26{
27 node *q;
28 char *key = (char *)vkey;
29 node **rootp = (node **)vrootp;
30
31 if (rootp == (struct node_t **)0)
32 return ((void *)0);
33 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
34 int r;
35
36 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
37 return ((void *)*rootp); /* we found it! */
38 rootp = (r < 0) ?
39 &(*rootp)->left : /* T3: follow left branch */
40 &(*rootp)->right; /* T4: follow right branch */
41 }
42 q = malloc(sizeof(node)); /* T5: key not found */
43 if (q != (struct node_t *)0) { /* make new node */
44 *rootp = q; /* link new node to old */
45 q->key = key; /* initialize new node */
46 q->left = q->right = (struct node_t *)0;
47 }
48 return ((void *)q);
49}
50
51/* delete node with given key */
52void *
53tdelete(const void *vkey, void **vrootp,
54 int (*compar)(const void *, const void *))
55{
56 node **rootp = (node **)vrootp;
57 char *key = (char *)vkey;
58 node *p = (node *)1;
59 node *q;
60 node *r;
61 int cmp;
62
63 if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
64 return ((struct node_t *)0);
65 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
66 p = *rootp;
67 rootp = (cmp < 0) ?
68 &(*rootp)->left : /* follow left branch */
69 &(*rootp)->right; /* follow right branch */
70 if (*rootp == (struct node_t *)0)
71 return ((void *)0); /* key not found */
72 }
73 r = (*rootp)->right; /* D1: */
74 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
75 q = r;
76 else if (r != (struct node_t *)0) { /* Right link is null? */
77 if (r->left == (struct node_t *)0) { /* D2: Find successor */
78 r->left = q;
79 q = r;
80 } else { /* D3: Find (struct node_t *)0 link */
81 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
82 r = q;
83 r->left = q->right;
84 q->left = (*rootp)->left;
85 q->right = (*rootp)->right;
86 }
87 }
88 free((struct node_t *) *rootp); /* D4: Free node */
89 *rootp = q; /* link parent to new node */
90 return(p);
91}
92
93/* Walk the nodes of a tree */
94static void
95trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
96{
97 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
98 (*action)(root, leaf, level);
99 else {
100 (*action)(root, preorder, level);
101 if (root->left != (struct node_t *)0)
102 trecurse(root->left, action, level + 1);
103 (*action)(root, postorder, level);
104 if (root->right != (struct node_t *)0)
105 trecurse(root->right, action, level + 1);
106 (*action)(root, endorder, level);
107 }
108}
109
110/* Walk the nodes of a tree */
111void
112twalk(const void *vroot, void (*action)(const void *, VISIT, int))
113{
114 node *root = (node *)vroot;
115
116 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
117 trecurse(root, action, 0);
118}