summaryrefslogtreecommitdiff
path: root/src/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc')
-rw-r--r--src/lib/libc/crypt/Makefile.inc15
-rw-r--r--src/lib/libc/crypt/arc4random.3110
-rw-r--r--src/lib/libc/crypt/arc4random.c182
-rw-r--r--src/lib/libc/crypt/bcrypt.c336
-rw-r--r--src/lib/libc/crypt/blowfish.3106
-rw-r--r--src/lib/libc/crypt/blowfish.c685
-rw-r--r--src/lib/libc/crypt/cast.c790
-rw-r--r--src/lib/libc/crypt/crypt.3321
-rw-r--r--src/lib/libc/crypt/crypt.c700
-rw-r--r--src/lib/libc/crypt/crypt2.c108
-rw-r--r--src/lib/libc/crypt/md5crypt.c153
-rw-r--r--src/lib/libc/crypt/skipjack.c260
-rw-r--r--src/lib/libc/include/namespace.h18
-rw-r--r--src/lib/libc/include/thread_private.h126
-rw-r--r--src/lib/libc/net/Makefile.inc92
-rw-r--r--src/lib/libc/net/base64.c318
-rw-r--r--src/lib/libc/net/byteorder.3206
-rw-r--r--src/lib/libc/net/ethers.3119
-rw-r--r--src/lib/libc/net/ethers.c236
-rw-r--r--src/lib/libc/net/freeaddrinfo.c50
-rw-r--r--src/lib/libc/net/gai_strerror.393
-rw-r--r--src/lib/libc/net/gai_strerror.c76
-rw-r--r--src/lib/libc/net/getaddrinfo.3439
-rw-r--r--src/lib/libc/net/getaddrinfo.c1804
-rw-r--r--src/lib/libc/net/gethostbyname.3296
-rw-r--r--src/lib/libc/net/gethostnamadr.c1142
-rw-r--r--src/lib/libc/net/getifaddrs.3158
-rw-r--r--src/lib/libc/net/getifaddrs.c277
-rw-r--r--src/lib/libc/net/getnameinfo.3270
-rw-r--r--src/lib/libc/net/getnameinfo.c356
-rw-r--r--src/lib/libc/net/getnetbyaddr.c50
-rw-r--r--src/lib/libc/net/getnetbyname.c57
-rw-r--r--src/lib/libc/net/getnetent.3140
-rw-r--r--src/lib/libc/net/getnetent.c124
-rw-r--r--src/lib/libc/net/getnetnamadr.c394
-rw-r--r--src/lib/libc/net/getproto.c62
-rw-r--r--src/lib/libc/net/getprotoent.3213
-rw-r--r--src/lib/libc/net/getprotoent.c168
-rw-r--r--src/lib/libc/net/getprotoname.c70
-rw-r--r--src/lib/libc/net/getrrsetbyname.3165
-rw-r--r--src/lib/libc/net/getrrsetbyname.c514
-rw-r--r--src/lib/libc/net/getservbyname.c73
-rw-r--r--src/lib/libc/net/getservbyport.c67
-rw-r--r--src/lib/libc/net/getservent.3220
-rw-r--r--src/lib/libc/net/getservent.c170
-rw-r--r--src/lib/libc/net/herror.c115
-rw-r--r--src/lib/libc/net/htonl.c24
-rw-r--r--src/lib/libc/net/htons.c24
-rw-r--r--src/lib/libc/net/if_indextoname.3136
-rw-r--r--src/lib/libc/net/if_indextoname.c86
-rw-r--r--src/lib/libc/net/if_nameindex.c140
-rw-r--r--src/lib/libc/net/if_nametoindex.c81
-rw-r--r--src/lib/libc/net/inet.3355
-rw-r--r--src/lib/libc/net/inet6_option_space.3438
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3308
-rw-r--r--src/lib/libc/net/inet_addr.c180
-rw-r--r--src/lib/libc/net/inet_lnaof.c54
-rw-r--r--src/lib/libc/net/inet_makeaddr.c57
-rw-r--r--src/lib/libc/net/inet_net.3181
-rw-r--r--src/lib/libc/net/inet_net_ntop.c143
-rw-r--r--src/lib/libc/net/inet_net_pton.c199
-rw-r--r--src/lib/libc/net/inet_neta.c84
-rw-r--r--src/lib/libc/net/inet_netof.c53
-rw-r--r--src/lib/libc/net/inet_network.c87
-rw-r--r--src/lib/libc/net/inet_ntoa.c54
-rw-r--r--src/lib/libc/net/inet_ntop.c203
-rw-r--r--src/lib/libc/net/inet_pton.c215
-rw-r--r--src/lib/libc/net/ip6opt.c371
-rw-r--r--src/lib/libc/net/ipx.3123
-rw-r--r--src/lib/libc/net/ipx_addr.c216
-rw-r--r--src/lib/libc/net/ipx_ntoa.c49
-rw-r--r--src/lib/libc/net/link_addr.3126
-rw-r--r--src/lib/libc/net/linkaddr.c151
-rw-r--r--src/lib/libc/net/net_addrcmp.391
-rw-r--r--src/lib/libc/net/net_addrcmp.c68
-rw-r--r--src/lib/libc/net/ns.3127
-rw-r--r--src/lib/libc/net/ns_addr.c214
-rw-r--r--src/lib/libc/net/ns_ntoa.c106
-rw-r--r--src/lib/libc/net/nsap_addr.c102
-rw-r--r--src/lib/libc/net/ntohl.c24
-rw-r--r--src/lib/libc/net/ntohs.c24
-rw-r--r--src/lib/libc/net/rcmd.3266
-rw-r--r--src/lib/libc/net/rcmd.c691
-rw-r--r--src/lib/libc/net/rcmdsh.396
-rw-r--r--src/lib/libc/net/rcmdsh.c190
-rw-r--r--src/lib/libc/net/recv.c43
-rw-r--r--src/lib/libc/net/res_comp.c483
-rw-r--r--src/lib/libc/net/res_data.c113
-rw-r--r--src/lib/libc/net/res_debug.c1509
-rw-r--r--src/lib/libc/net/res_init.c678
-rw-r--r--src/lib/libc/net/res_mkquery.c241
-rw-r--r--src/lib/libc/net/res_query.c407
-rw-r--r--src/lib/libc/net/res_random.c228
-rw-r--r--src/lib/libc/net/res_send.c879
-rw-r--r--src/lib/libc/net/resolver.3354
-rw-r--r--src/lib/libc/net/rresvport.c110
-rw-r--r--src/lib/libc/net/rthdr.c215
-rw-r--r--src/lib/libc/net/send.c43
-rw-r--r--src/lib/libc/net/sethostent.c60
-rw-r--r--src/lib/libc/net/vars6.c42
-rw-r--r--src/lib/libc/stdlib/Makefile.inc71
-rw-r--r--src/lib/libc/stdlib/_Exit.c26
-rw-r--r--src/lib/libc/stdlib/_rand48.c50
-rw-r--r--src/lib/libc/stdlib/a64l.3133
-rw-r--r--src/lib/libc/stdlib/a64l.c45
-rw-r--r--src/lib/libc/stdlib/abort.363
-rw-r--r--src/lib/libc/stdlib/abort.c78
-rw-r--r--src/lib/libc/stdlib/abs.365
-rw-r--r--src/lib/libc/stdlib/abs.c40
-rw-r--r--src/lib/libc/stdlib/alloca.380
-rw-r--r--src/lib/libc/stdlib/atexit.371
-rw-r--r--src/lib/libc/stdlib/atexit.c133
-rw-r--r--src/lib/libc/stdlib/atexit.h41
-rw-r--r--src/lib/libc/stdlib/atof.369
-rw-r--r--src/lib/libc/stdlib/atof.c40
-rw-r--r--src/lib/libc/stdlib/atoi.386
-rw-r--r--src/lib/libc/stdlib/atoi.c40
-rw-r--r--src/lib/libc/stdlib/atol.370
-rw-r--r--src/lib/libc/stdlib/atol.c40
-rw-r--r--src/lib/libc/stdlib/atoll.370
-rw-r--r--src/lib/libc/stdlib/atoll.c41
-rw-r--r--src/lib/libc/stdlib/bsearch.384
-rw-r--r--src/lib/libc/stdlib/bsearch.c71
-rw-r--r--src/lib/libc/stdlib/calloc.c53
-rw-r--r--src/lib/libc/stdlib/cfree.c44
-rw-r--r--src/lib/libc/stdlib/div.363
-rw-r--r--src/lib/libc/stdlib/div.c74
-rw-r--r--src/lib/libc/stdlib/drand48.c26
-rw-r--r--src/lib/libc/stdlib/ecvt.3165
-rw-r--r--src/lib/libc/stdlib/ecvt.c103
-rw-r--r--src/lib/libc/stdlib/erand48.c27
-rw-r--r--src/lib/libc/stdlib/exit.3114
-rw-r--r--src/lib/libc/stdlib/exit.c72
-rw-r--r--src/lib/libc/stdlib/gcvt.c99
-rw-r--r--src/lib/libc/stdlib/getenv.3142
-rw-r--r--src/lib/libc/stdlib/getenv.c83
-rw-r--r--src/lib/libc/stdlib/getopt.3372
-rw-r--r--src/lib/libc/stdlib/getopt_long.3377
-rw-r--r--src/lib/libc/stdlib/getopt_long.c537
-rw-r--r--src/lib/libc/stdlib/getsubopt.3143
-rw-r--r--src/lib/libc/stdlib/getsubopt.c100
-rw-r--r--src/lib/libc/stdlib/hcreate.3195
-rw-r--r--src/lib/libc/stdlib/hcreate.c200
-rw-r--r--src/lib/libc/stdlib/heapsort.c177
-rw-r--r--src/lib/libc/stdlib/insque.3100
-rw-r--r--src/lib/libc/stdlib/insque.c52
-rw-r--r--src/lib/libc/stdlib/jrand48.c25
-rw-r--r--src/lib/libc/stdlib/l64a.c45
-rw-r--r--src/lib/libc/stdlib/labs.368
-rw-r--r--src/lib/libc/stdlib/labs.c40
-rw-r--r--src/lib/libc/stdlib/lcong48.c34
-rw-r--r--src/lib/libc/stdlib/ldiv.365
-rw-r--r--src/lib/libc/stdlib/ldiv.c53
-rw-r--r--src/lib/libc/stdlib/llabs.c45
-rw-r--r--src/lib/libc/stdlib/lrand48.c27
-rw-r--r--src/lib/libc/stdlib/lsearch.3105
-rw-r--r--src/lib/libc/stdlib/lsearch.c88
-rw-r--r--src/lib/libc/stdlib/malloc.3431
-rw-r--r--src/lib/libc/stdlib/malloc.c1698
-rw-r--r--src/lib/libc/stdlib/merge.c336
-rw-r--r--src/lib/libc/stdlib/mrand48.c27
-rw-r--r--src/lib/libc/stdlib/multibyte.c120
-rw-r--r--src/lib/libc/stdlib/nrand48.c25
-rw-r--r--src/lib/libc/stdlib/putenv.c53
-rw-r--r--src/lib/libc/stdlib/qabs.356
-rw-r--r--src/lib/libc/stdlib/qabs.c40
-rw-r--r--src/lib/libc/stdlib/qdiv.360
-rw-r--r--src/lib/libc/stdlib/qdiv.c53
-rw-r--r--src/lib/libc/stdlib/qsort.3233
-rw-r--r--src/lib/libc/stdlib/qsort.c164
-rw-r--r--src/lib/libc/stdlib/radixsort.3155
-rw-r--r--src/lib/libc/stdlib/radixsort.c297
-rw-r--r--src/lib/libc/stdlib/rand.398
-rw-r--r--src/lib/libc/stdlib/rand.c56
-rw-r--r--src/lib/libc/stdlib/rand48.3165
-rw-r--r--src/lib/libc/stdlib/rand48.h32
-rw-r--r--src/lib/libc/stdlib/random.3186
-rw-r--r--src/lib/libc/stdlib/random.c425
-rw-r--r--src/lib/libc/stdlib/realpath.3117
-rw-r--r--src/lib/libc/stdlib/realpath.c198
-rw-r--r--src/lib/libc/stdlib/remque.c48
-rw-r--r--src/lib/libc/stdlib/seed48.c40
-rw-r--r--src/lib/libc/stdlib/setenv.c106
-rw-r--r--src/lib/libc/stdlib/srand48.c34
-rw-r--r--src/lib/libc/stdlib/strtod.3113
-rw-r--r--src/lib/libc/stdlib/strtod.c2411
-rw-r--r--src/lib/libc/stdlib/strtol.3247
-rw-r--r--src/lib/libc/stdlib/strtol.c143
-rw-r--r--src/lib/libc/stdlib/strtoll.c156
-rw-r--r--src/lib/libc/stdlib/strtonum.3151
-rw-r--r--src/lib/libc/stdlib/strtonum.c65
-rw-r--r--src/lib/libc/stdlib/strtoul.3231
-rw-r--r--src/lib/libc/stdlib/strtoul.c105
-rw-r--r--src/lib/libc/stdlib/strtoull.c118
-rw-r--r--src/lib/libc/stdlib/system.399
-rw-r--r--src/lib/libc/stdlib/system.c77
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3116
-rw-r--r--src/lib/libc/stdlib/tsearch.c119
-rw-r--r--src/lib/libc/string/Makefile.inc177
-rw-r--r--src/lib/libc/string/__strsignal.c95
-rw-r--r--src/lib/libc/string/bcmp.366
-rw-r--r--src/lib/libc/string/bcmp.c59
-rw-r--r--src/lib/libc/string/bcopy.367
-rw-r--r--src/lib/libc/string/bcopy.c131
-rw-r--r--src/lib/libc/string/bm.3111
-rw-r--r--src/lib/libc/string/bm.c208
-rw-r--r--src/lib/libc/string/bstring.398
-rw-r--r--src/lib/libc/string/bzero.361
-rw-r--r--src/lib/libc/string/bzero.c52
-rw-r--r--src/lib/libc/string/ffs.356
-rw-r--r--src/lib/libc/string/ffs.c48
-rw-r--r--src/lib/libc/string/index.c50
-rw-r--r--src/lib/libc/string/memccpy.373
-rw-r--r--src/lib/libc/string/memccpy.c56
-rw-r--r--src/lib/libc/string/memchr.374
-rw-r--r--src/lib/libc/string/memchr.c51
-rw-r--r--src/lib/libc/string/memcmp.377
-rw-r--r--src/lib/libc/string/memcmp.c54
-rw-r--r--src/lib/libc/string/memcpy.377
-rw-r--r--src/lib/libc/string/memmove.370
-rw-r--r--src/lib/libc/string/memset.367
-rw-r--r--src/lib/libc/string/memset.c51
-rw-r--r--src/lib/libc/string/rindex.c52
-rw-r--r--src/lib/libc/string/strcasecmp.384
-rw-r--r--src/lib/libc/string/strcasecmp.c113
-rw-r--r--src/lib/libc/string/strcasestr.c64
-rw-r--r--src/lib/libc/string/strcat.3131
-rw-r--r--src/lib/libc/string/strcat.c55
-rw-r--r--src/lib/libc/string/strchr.3102
-rw-r--r--src/lib/libc/string/strcmp.387
-rw-r--r--src/lib/libc/string/strcmp.c55
-rw-r--r--src/lib/libc/string/strcoll.368
-rw-r--r--src/lib/libc/string/strcoll.c47
-rw-r--r--src/lib/libc/string/strcpy.3150
-rw-r--r--src/lib/libc/string/strcpy.c54
-rw-r--r--src/lib/libc/string/strcspn.388
-rw-r--r--src/lib/libc/string/strcspn.c61
-rw-r--r--src/lib/libc/string/strdup.384
-rw-r--r--src/lib/libc/string/strdup.c57
-rw-r--r--src/lib/libc/string/strerror.3113
-rw-r--r--src/lib/libc/string/strerror.c44
-rw-r--r--src/lib/libc/string/strerror_r.c124
-rw-r--r--src/lib/libc/string/string.3136
-rw-r--r--src/lib/libc/string/strlcat.c59
-rw-r--r--src/lib/libc/string/strlcpy.3179
-rw-r--r--src/lib/libc/string/strlcpy.c55
-rw-r--r--src/lib/libc/string/strlen.361
-rw-r--r--src/lib/libc/string/strlen.c51
-rw-r--r--src/lib/libc/string/strmode.3159
-rw-r--r--src/lib/libc/string/strmode.c148
-rw-r--r--src/lib/libc/string/strncat.c60
-rw-r--r--src/lib/libc/string/strncmp.c55
-rw-r--r--src/lib/libc/string/strncpy.c66
-rw-r--r--src/lib/libc/string/strpbrk.372
-rw-r--r--src/lib/libc/string/strpbrk.c51
-rw-r--r--src/lib/libc/string/strrchr.3104
-rw-r--r--src/lib/libc/string/strsep.3112
-rw-r--r--src/lib/libc/string/strsep.c79
-rw-r--r--src/lib/libc/string/strsignal.356
-rw-r--r--src/lib/libc/string/strsignal.c45
-rw-r--r--src/lib/libc/string/strspn.384
-rw-r--r--src/lib/libc/string/strspn.c54
-rw-r--r--src/lib/libc/string/strstr.387
-rw-r--r--src/lib/libc/string/strstr.c59
-rw-r--r--src/lib/libc/string/strtok.3152
-rw-r--r--src/lib/libc/string/strtok.c90
-rw-r--r--src/lib/libc/string/strxfrm.362
-rw-r--r--src/lib/libc/string/strxfrm.c54
-rw-r--r--src/lib/libc/string/swab.361
-rw-r--r--src/lib/libc/string/swab.c58
-rw-r--r--src/lib/libc/string/wcscat.c56
-rw-r--r--src/lib/libc/string/wcschr.c54
-rw-r--r--src/lib/libc/string/wcscmp.c56
-rw-r--r--src/lib/libc/string/wcscpy.c53
-rw-r--r--src/lib/libc/string/wcscspn.c59
-rw-r--r--src/lib/libc/string/wcslcat.c75
-rw-r--r--src/lib/libc/string/wcslcpy.c71
-rw-r--r--src/lib/libc/string/wcslen.c49
-rw-r--r--src/lib/libc/string/wcsncat.c59
-rw-r--r--src/lib/libc/string/wcsncmp.c58
-rw-r--r--src/lib/libc/string/wcsncpy.c57
-rw-r--r--src/lib/libc/string/wcspbrk.c59
-rw-r--r--src/lib/libc/string/wcsrchr.c56
-rw-r--r--src/lib/libc/string/wcsspn.c61
-rw-r--r--src/lib/libc/string/wcsstr.c76
-rw-r--r--src/lib/libc/string/wcstok.3136
-rw-r--r--src/lib/libc/string/wcstok.c99
-rw-r--r--src/lib/libc/string/wcswcs.c5
-rw-r--r--src/lib/libc/string/wcswidth.c53
-rw-r--r--src/lib/libc/string/wmemchr.3141
-rw-r--r--src/lib/libc/string/wmemchr.c54
-rw-r--r--src/lib/libc/string/wmemcmp.c57
-rw-r--r--src/lib/libc/string/wmemcpy.c47
-rw-r--r--src/lib/libc/string/wmemmove.c47
-rw-r--r--src/lib/libc/string/wmemset.c53
296 files changed, 46313 insertions, 0 deletions
diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc
new file mode 100644
index 0000000000..131e1d3f39
--- /dev/null
+++ b/src/lib/libc/crypt/Makefile.inc
@@ -0,0 +1,15 @@
1# $OpenBSD: Makefile.inc,v 1.15 2003/08/12 01:22:17 deraadt Exp $
2
3.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/crypt ${LIBCSRCDIR}/crypt
4
5SRCS+= cast.c crypt.c crypt2.c md5crypt.c arc4random.c blowfish.c
6SRCS+= bcrypt.c skipjack.c
7
8MAN+= crypt.3 blowfish.3 arc4random.3
9MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3
10MLINKS+=crypt.3 bcrypt_gensalt.3 crypt.3 bcrypt.3 crypt.3 md5crypt.3
11MLINKS+=crypt.3 des_setkey.3 blowfish.3 blf_key.3 blowfish.3 blf_enc.3
12MLINKS+=blowfish.3 blf_dec.3 blowfish.3 blf_ecb_encrypt.3
13MLINKS+=blowfish.3 blf_ecb_decrypt.3 blowfish.3 blf_cbc_encrypt.3
14MLINKS+=blowfish.3 blf_cbc_decrypt.3
15MLINKS+=arc4random.3 arc4random_stir.3 arc4random.3 arc4random_addrandom.3
diff --git a/src/lib/libc/crypt/arc4random.3 b/src/lib/libc/crypt/arc4random.3
new file mode 100644
index 0000000000..d8e0f8cda6
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.3
@@ -0,0 +1,110 @@
1.\" $OpenBSD: arc4random.3,v 1.17 2000/12/21 14:07:41 aaron Exp $
2.\"
3.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
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. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by Niels Provos.
17.\" 4. The name of the author may not be used to endorse or promote products
18.\" derived from this software without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.\"
31.\" Manual page, using -mandoc macros
32.\"
33.Dd April 15, 1997
34.Dt ARC4RANDOM 3
35.Os
36.Sh NAME
37.Nm arc4random ,
38.Nm arc4random_stir ,
39.Nm arc4random_addrandom
40.Nd arc4 random number generator
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft u_int32_t
44.Fn arc4random "void"
45.Ft void
46.Fn arc4random_stir "void"
47.Ft void
48.Fn arc4random_addrandom "u_char *dat" "int datlen"
49.Sh DESCRIPTION
50The
51.Fn arc4random
52function provides a high quality 32-bit pseudo-random
53number very quickly.
54.Fn arc4random
55seeds itself on a regular basis from the kernel strong random number
56subsystem described in
57.Xr random 4 .
58On each call, an ARC4 generator is used to generate a new result.
59The
60.Fn arc4random
61function uses the ARC4 cipher key stream generator,
62which uses 8*8 8 bit S-Boxes.
63The S-Boxes can be in about (2**1700) states.
64.Pp
65.Fn arc4random
66fits into a middle ground not covered by other subsystems such as
67the strong, slow, and resource expensive random
68devices described in
69.Xr random 4
70versus the fast but poor quality interfaces described in
71.Xr rand 3 ,
72.Xr random 3 ,
73and
74.Xr drand48 3 .
75.Pp
76The
77.Fn arc4random_stir
78function reads data from
79.Pa /dev/arandom
80and uses it to permute the S-Boxes via
81.Fn arc4random_addrandom .
82.Pp
83There is no need to call
84.Fn arc4random_stir
85before using
86.Fn arc4random ,
87since
88.Fn arc4random
89automatically initializes itself.
90.Sh SEE ALSO
91.Xr rand 3 ,
92.Xr rand48 3 ,
93.Xr random 3
94.Sh HISTORY
95An algorithm called
96.Pa RC4
97was designed by RSA Data Security, Inc.
98It was considered a trade secret, but not trademarked.
99Because it was a trade secret, it obviously could not be patented.
100A clone of this was posted anonymously to USENET and confirmed to
101be equivalent by several sources who had access to the original cipher.
102Because of the trade secret situation, RSA Data Security, Inc. can do
103nothing about the release of the ARC4 algorithm.
104Since
105.Pa RC4
106used to be a trade secret, the cipher is now referred to as
107.Pa ARC4 .
108.Pp
109These functions first appeared in
110.Ox 2.1 .
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
new file mode 100644
index 0000000000..5c768f5494
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.c
@@ -0,0 +1,182 @@
1/* $OpenBSD: arc4random.c,v 1.11 2004/11/02 11:07:13 hshoexer Exp $ */
2
3/*
4 * Arc4 random number generator for OpenBSD.
5 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
6 *
7 * Modification and redistribution in source and binary forms is
8 * permitted provided that due credit is given to the author and the
9 * OpenBSD project by leaving this copyright notice intact.
10 */
11
12/*
13 * This code is derived from section 17.1 of Applied Cryptography,
14 * second edition, which describes a stream cipher allegedly
15 * compatible with RSA Labs "RC4" cipher (the actual description of
16 * which is a trade secret). The same algorithm is used as a stream
17 * cipher called "arcfour" in Tatu Ylonen's ssh package.
18 *
19 * Here the stream cipher has been modified always to include the time
20 * when initializing the state. That makes it impossible to
21 * regenerate the same random sequence twice, so this can't be used
22 * for encryption, but will generate good random numbers.
23 *
24 * RC4 is a registered trademark of RSA Laboratories.
25 */
26
27#include <fcntl.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <sys/types.h>
31#include <sys/param.h>
32#include <sys/time.h>
33#include <sys/sysctl.h>
34
35#ifdef __GNUC__
36#define inline __inline
37#else /* !__GNUC__ */
38#define inline
39#endif /* !__GNUC__ */
40
41struct arc4_stream {
42 u_int8_t i;
43 u_int8_t j;
44 u_int8_t s[256];
45};
46
47static int rs_initialized;
48static struct arc4_stream rs;
49static pid_t arc4_stir_pid;
50
51static inline u_int8_t arc4_getbyte(struct arc4_stream *);
52
53static inline void
54arc4_init(struct arc4_stream *as)
55{
56 int n;
57
58 for (n = 0; n < 256; n++)
59 as->s[n] = n;
60 as->i = 0;
61 as->j = 0;
62}
63
64static inline void
65arc4_addrandom(struct arc4_stream *as, u_char *dat, int datlen)
66{
67 int n;
68 u_int8_t si;
69
70 as->i--;
71 for (n = 0; n < 256; n++) {
72 as->i = (as->i + 1);
73 si = as->s[as->i];
74 as->j = (as->j + si + dat[n % datlen]);
75 as->s[as->i] = as->s[as->j];
76 as->s[as->j] = si;
77 }
78 as->j = as->i;
79}
80
81static void
82arc4_stir(struct arc4_stream *as)
83{
84 int i, mib[2];
85 size_t len;
86 struct {
87 struct timeval tv;
88 u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
89 } rdat;
90
91 gettimeofday(&rdat.tv, NULL);
92 mib[0] = CTL_KERN;
93 mib[1] = KERN_ARND;
94
95 for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
96 len = sizeof(u_int);
97 if (sysctl(mib, 2, &rdat.rnd[i], &len, NULL, 0) == -1)
98 break;
99 }
100
101 arc4_stir_pid = getpid();
102 arc4_addrandom(as, (void *)&rdat, sizeof(rdat));
103
104 /*
105 * Discard early keystream, as per recommendations in:
106 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
107 */
108 for (i = 0; i < 256; i++)
109 (void)arc4_getbyte(as);
110}
111
112static inline u_int8_t
113arc4_getbyte(struct arc4_stream *as)
114{
115 u_int8_t si, sj;
116
117 as->i = (as->i + 1);
118 si = as->s[as->i];
119 as->j = (as->j + si);
120 sj = as->s[as->j];
121 as->s[as->i] = sj;
122 as->s[as->j] = si;
123 return (as->s[(si + sj) & 0xff]);
124}
125
126static inline u_int32_t
127arc4_getword(struct arc4_stream *as)
128{
129 u_int32_t val;
130 val = arc4_getbyte(as) << 24;
131 val |= arc4_getbyte(as) << 16;
132 val |= arc4_getbyte(as) << 8;
133 val |= arc4_getbyte(as);
134 return val;
135}
136
137void
138arc4random_stir(void)
139{
140 if (!rs_initialized) {
141 arc4_init(&rs);
142 rs_initialized = 1;
143 }
144 arc4_stir(&rs);
145}
146
147void
148arc4random_addrandom(u_char *dat, int datlen)
149{
150 if (!rs_initialized)
151 arc4random_stir();
152 arc4_addrandom(&rs, dat, datlen);
153}
154
155u_int32_t
156arc4random(void)
157{
158 if (!rs_initialized || arc4_stir_pid != getpid())
159 arc4random_stir();
160 return arc4_getword(&rs);
161}
162
163#if 0
164/*-------- Test code for i386 --------*/
165#include <stdio.h>
166#include <machine/pctr.h>
167int
168main(int argc, char **argv)
169{
170 const int iter = 1000000;
171 int i;
172 pctrval v;
173
174 v = rdtsc();
175 for (i = 0; i < iter; i++)
176 arc4random();
177 v = rdtsc() - v;
178 v /= iter;
179
180 printf("%qd cycles\n", v);
181}
182#endif
diff --git a/src/lib/libc/crypt/bcrypt.c b/src/lib/libc/crypt/bcrypt.c
new file mode 100644
index 0000000000..6e1ae04e1b
--- /dev/null
+++ b/src/lib/libc/crypt/bcrypt.c
@@ -0,0 +1,336 @@
1/* $OpenBSD: bcrypt.c,v 1.19 2004/12/22 17:33:25 otto Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niels Provos.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* This password hashing algorithm was designed by David Mazieres
34 * <dm@lcs.mit.edu> and works as follows:
35 *
36 * 1. state := InitState ()
37 * 2. state := ExpandKey (state, salt, password) 3.
38 * REPEAT rounds:
39 * state := ExpandKey (state, 0, salt)
40 * state := ExpandKey(state, 0, password)
41 * 4. ctext := "OrpheanBeholderScryDoubt"
42 * 5. REPEAT 64:
43 * ctext := Encrypt_ECB (state, ctext);
44 * 6. RETURN Concatenate (salt, ctext);
45 *
46 */
47
48#if 0
49#include <stdio.h>
50#endif
51
52#include <stdio.h>
53#include <stdlib.h>
54#include <sys/types.h>
55#include <string.h>
56#include <pwd.h>
57#include <blf.h>
58
59/* This implementation is adaptable to current computing power.
60 * You can have up to 2^31 rounds which should be enough for some
61 * time to come.
62 */
63
64#define BCRYPT_VERSION '2'
65#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
66#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
67#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
68
69char *bcrypt_gensalt(u_int8_t);
70
71static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
72static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
73static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
74
75static char encrypted[_PASSWORD_LEN];
76static char gsalt[BCRYPT_MAXSALT * 4 / 3 + 1];
77static char error[] = ":";
78
79const static u_int8_t Base64Code[] =
80"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
81
82const static u_int8_t index_64[128] = {
83 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
84 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
88 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
89 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
90 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
91 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
92 255, 255, 255, 255, 255, 255, 28, 29, 30,
93 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
94 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
95 51, 52, 53, 255, 255, 255, 255, 255
96};
97#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
98
99static void
100decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
101{
102 u_int8_t *bp = buffer;
103 u_int8_t *p = data;
104 u_int8_t c1, c2, c3, c4;
105 while (bp < buffer + len) {
106 c1 = CHAR64(*p);
107 c2 = CHAR64(*(p + 1));
108
109 /* Invalid data */
110 if (c1 == 255 || c2 == 255)
111 break;
112
113 *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
114 if (bp >= buffer + len)
115 break;
116
117 c3 = CHAR64(*(p + 2));
118 if (c3 == 255)
119 break;
120
121 *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
122 if (bp >= buffer + len)
123 break;
124
125 c4 = CHAR64(*(p + 3));
126 if (c4 == 255)
127 break;
128 *bp++ = ((c3 & 0x03) << 6) | c4;
129
130 p += 4;
131 }
132}
133
134static void
135encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
136{
137 salt[0] = '$';
138 salt[1] = BCRYPT_VERSION;
139 salt[2] = 'a';
140 salt[3] = '$';
141
142 snprintf(salt + 4, 4, "%2.2u$", logr);
143
144 encode_base64((u_int8_t *) salt + 7, csalt, clen);
145}
146/* Generates a salt for this version of crypt.
147 Since versions may change. Keeping this here
148 seems sensible.
149 */
150
151char *
152bcrypt_gensalt(u_int8_t log_rounds)
153{
154 u_int8_t csalt[BCRYPT_MAXSALT];
155 u_int16_t i;
156 u_int32_t seed = 0;
157
158 for (i = 0; i < BCRYPT_MAXSALT; i++) {
159 if (i % 4 == 0)
160 seed = arc4random();
161 csalt[i] = seed & 0xff;
162 seed = seed >> 8;
163 }
164
165 if (log_rounds < 4)
166 log_rounds = 4;
167 else if (log_rounds > 31)
168 log_rounds = 31;
169
170 encode_salt(gsalt, csalt, BCRYPT_MAXSALT, log_rounds);
171 return gsalt;
172}
173/* We handle $Vers$log2(NumRounds)$salt+passwd$
174 i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
175
176char *
177bcrypt(const char *key, const char *salt)
178{
179 blf_ctx state;
180 u_int32_t rounds, i, k;
181 u_int16_t j;
182 u_int8_t key_len, salt_len, logr, minor;
183 u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
184 u_int8_t csalt[BCRYPT_MAXSALT];
185 u_int32_t cdata[BCRYPT_BLOCKS];
186
187 /* Discard "$" identifier */
188 salt++;
189
190 if (*salt > BCRYPT_VERSION) {
191 /* How do I handle errors ? Return ':' */
192 return error;
193 }
194
195 /* Check for minor versions */
196 if (salt[1] != '$') {
197 switch (salt[1]) {
198 case 'a':
199 /* 'ab' should not yield the same as 'abab' */
200 minor = salt[1];
201 salt++;
202 break;
203 default:
204 return error;
205 }
206 } else
207 minor = 0;
208
209 /* Discard version + "$" identifier */
210 salt += 2;
211
212 if (salt[2] != '$')
213 /* Out of sync with passwd entry */
214 return error;
215
216 /* Computer power doesn't increase linear, 2^x should be fine */
217 logr = atoi(salt);
218 if (logr > 31)
219 return error;
220 if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS)
221 return error;
222
223 /* Discard num rounds + "$" identifier */
224 salt += 3;
225
226 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
227 return error;
228
229 /* We dont want the base64 salt but the raw data */
230 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
231 salt_len = BCRYPT_MAXSALT;
232 key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
233
234 /* Setting up S-Boxes and Subkeys */
235 Blowfish_initstate(&state);
236 Blowfish_expandstate(&state, csalt, salt_len,
237 (u_int8_t *) key, key_len);
238 for (k = 0; k < rounds; k++) {
239 Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
240 Blowfish_expand0state(&state, csalt, salt_len);
241 }
242
243 /* This can be precomputed later */
244 j = 0;
245 for (i = 0; i < BCRYPT_BLOCKS; i++)
246 cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
247
248 /* Now do the encryption */
249 for (k = 0; k < 64; k++)
250 blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
251
252 for (i = 0; i < BCRYPT_BLOCKS; i++) {
253 ciphertext[4 * i + 3] = cdata[i] & 0xff;
254 cdata[i] = cdata[i] >> 8;
255 ciphertext[4 * i + 2] = cdata[i] & 0xff;
256 cdata[i] = cdata[i] >> 8;
257 ciphertext[4 * i + 1] = cdata[i] & 0xff;
258 cdata[i] = cdata[i] >> 8;
259 ciphertext[4 * i + 0] = cdata[i] & 0xff;
260 }
261
262
263 i = 0;
264 encrypted[i++] = '$';
265 encrypted[i++] = BCRYPT_VERSION;
266 if (minor)
267 encrypted[i++] = minor;
268 encrypted[i++] = '$';
269
270 snprintf(encrypted + i, 4, "%2.2u$", logr);
271
272 encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
273 encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
274 4 * BCRYPT_BLOCKS - 1);
275 return encrypted;
276}
277
278static void
279encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
280{
281 u_int8_t *bp = buffer;
282 u_int8_t *p = data;
283 u_int8_t c1, c2;
284 while (p < data + len) {
285 c1 = *p++;
286 *bp++ = Base64Code[(c1 >> 2)];
287 c1 = (c1 & 0x03) << 4;
288 if (p >= data + len) {
289 *bp++ = Base64Code[c1];
290 break;
291 }
292 c2 = *p++;
293 c1 |= (c2 >> 4) & 0x0f;
294 *bp++ = Base64Code[c1];
295 c1 = (c2 & 0x0f) << 2;
296 if (p >= data + len) {
297 *bp++ = Base64Code[c1];
298 break;
299 }
300 c2 = *p++;
301 c1 |= (c2 >> 6) & 0x03;
302 *bp++ = Base64Code[c1];
303 *bp++ = Base64Code[c2 & 0x3f];
304 }
305 *bp = '\0';
306}
307#if 0
308void
309main()
310{
311 char blubber[73];
312 char salt[100];
313 char *p;
314 salt[0] = '$';
315 salt[1] = BCRYPT_VERSION;
316 salt[2] = '$';
317
318 snprintf(salt + 3, 4, "%2.2u$", 5);
319
320 printf("24 bytes of salt: ");
321 fgets(salt + 6, 94, stdin);
322 salt[99] = 0;
323 printf("72 bytes of password: ");
324 fpurge(stdin);
325 fgets(blubber, 73, stdin);
326 blubber[72] = 0;
327
328 p = crypt(blubber, salt);
329 printf("Passwd entry: %s\n\n", p);
330
331 p = bcrypt_gensalt(5);
332 printf("Generated salt: %s\n", p);
333 p = crypt(blubber, p);
334 printf("Passwd entry: %s\n", p);
335}
336#endif
diff --git a/src/lib/libc/crypt/blowfish.3 b/src/lib/libc/crypt/blowfish.3
new file mode 100644
index 0000000000..44f7eb2bbf
--- /dev/null
+++ b/src/lib/libc/crypt/blowfish.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: blowfish.3,v 1.12 2003/08/28 12:35:00 jmc Exp $
2.\"
3.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
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. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by Niels Provos.
17.\" 4. The name of the author may not be used to endorse or promote products
18.\" derived from this software without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.\"
31.\" Manual page, using -mandoc macros
32.\"
33.Dd February 13, 1997
34.Dt BLOWFISH 3
35.Os
36.Sh NAME
37.Nm blf_key ,
38.Nm blf_enc ,
39.Nm blf_dec
40.Nd Blowfish encryption
41.Sh SYNOPSIS
42.Fd #include <blf.h>
43.Ft void
44.Fn blf_key "blf_ctx *state" "const u_int8_t *key" "u_int16_t keylen"
45.Ft void
46.Fn blf_enc "blf_ctx *state" "u_int32_t *data" "u_int16_t datalen"
47.Ft void
48.Fn blf_dec "blf_ctx *state" "u_int32_t *data" "u_int16_t datalen"
49.Ft void
50.Fn blf_ecb_encrypt "blf_ctx *state" "u_int8_t *data" "u_int32_t datalen"
51.Ft void
52.Fn blf_ecb_decrypt "blf_ctx *state" "u_int8_t *data" "u_int32_t datalen"
53.Ft void
54.Fn blf_cbc_encrypt "blf_ctx *state" "u_int8_t *iv" "u_int8_t *data" "u_int32_t datalen"
55.Ft void
56.Fn blf_cbc_decrypt "blf_ctx *state" "u_int8_t *iv" "u_int8_t *data" "u_int32_t datalen"
57.Sh DESCRIPTION
58.Pa Blowfish
59is a fast unpatented block cipher designed by Bruce Schneier.
60It basically consists of a 16 times iterated Feistel network.
61The block size is 64 bit and the maximum key size is 448 bit.
62.Pp
63The
64.Fn blf_key
65function initializes the 4 8bit S-boxes and the 18 Subkeys with
66the hexadecimal digits of Pi.
67The key is used for further randomization.
68The first argument to
69.Fn blf_enc
70is the initialized state derived from
71.Fn blf_key .
72The stream of 32-bit words is encrypted in Electronic Codebook
73Mode (ECB) and
74.Pa datalen
75must be even.
76.Fn blf_dec
77is used for decrypting Blowfish encrypted blocks.
78.Pp
79The functions
80.Fn blf_ecb_encrypt
81and
82.Fn blf_ecb_decrypt
83are used for encrypting and decrypting octet streams in ECB mode.
84The functions
85.Fn blf_cbc_encrypt
86and
87.Fn blf_cbc_decrypt
88are used for encrypting and decrypting octet streams in
89Cipherblock Chaining Mode (CBC).
90.Pp
91The functions
92.Fn Blowfish_initstate ,
93.Fn Blowfish_expand0state ,
94.Fn Blowfish_expandstate ,
95.Fn Blowfish_encipher
96and
97.Fn Blowfish_decipher
98are used for customization of the
99.Pa Blowfish
100cipher, e.g., for the blowfish password hashing function.
101.Sh SEE ALSO
102.Xr passwd 1 ,
103.Xr crypt 3 ,
104.Xr passwd 5
105.Sh AUTHORS
106.An Niels Provos Aq provos@physnet.uni-hamburg.de
diff --git a/src/lib/libc/crypt/blowfish.c b/src/lib/libc/crypt/blowfish.c
new file mode 100644
index 0000000000..c337df8a0a
--- /dev/null
+++ b/src/lib/libc/crypt/blowfish.c
@@ -0,0 +1,685 @@
1/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
2/*
3 * Blowfish block cipher for OpenBSD
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Niels Provos.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * This code is derived from section 14.3 and the given source
37 * in section V of Applied Cryptography, second edition.
38 * Blowfish is an unpatented fast block cipher designed by
39 * Bruce Schneier.
40 */
41
42#if 0
43#include <stdio.h> /* used for debugging */
44#include <string.h>
45#endif
46
47#include <sys/types.h>
48#include <blf.h>
49
50#undef inline
51#ifdef __GNUC__
52#define inline __inline
53#else /* !__GNUC__ */
54#define inline
55#endif /* !__GNUC__ */
56
57/* Function for Feistel Networks */
58
59#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
60 + (s)[0x100 + (((x)>>16)&0xFF)]) \
61 ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
62 + (s)[0x300 + ( (x) &0xFF)])
63
64#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
65
66void
67Blowfish_encipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
68{
69 u_int32_t Xl;
70 u_int32_t Xr;
71 u_int32_t *s = c->S[0];
72 u_int32_t *p = c->P;
73
74 Xl = *xl;
75 Xr = *xr;
76
77 Xl ^= p[0];
78 BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
79 BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
80 BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
81 BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
82 BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
83 BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
84 BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
85 BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
86
87 *xl = Xr ^ p[17];
88 *xr = Xl;
89}
90
91void
92Blowfish_decipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
93{
94 u_int32_t Xl;
95 u_int32_t Xr;
96 u_int32_t *s = c->S[0];
97 u_int32_t *p = c->P;
98
99 Xl = *xl;
100 Xr = *xr;
101
102 Xl ^= p[17];
103 BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
104 BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
105 BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
106 BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
107 BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
108 BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
109 BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
110 BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
111
112 *xl = Xr ^ p[0];
113 *xr = Xl;
114}
115
116void
117Blowfish_initstate(blf_ctx *c)
118{
119 /* P-box and S-box tables initialized with digits of Pi */
120
121 static const blf_ctx initstate =
122 { {
123 {
124 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
125 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
126 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
127 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
128 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
129 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
130 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
131 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
132 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
133 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
134 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
135 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
136 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
137 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
138 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
139 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
140 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
141 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
142 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
143 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
144 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
145 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
146 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
147 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
148 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
149 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
150 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
151 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
152 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
153 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
154 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
155 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
156 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
157 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
158 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
159 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
160 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
161 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
162 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
163 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
164 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
165 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
166 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
167 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
168 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
169 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
170 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
171 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
172 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
173 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
174 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
175 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
176 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
177 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
178 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
179 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
180 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
181 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
182 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
183 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
184 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
185 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
186 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
187 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
188 {
189 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
190 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
191 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
192 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
193 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
194 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
195 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
196 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
197 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
198 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
199 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
200 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
201 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
202 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
203 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
204 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
205 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
206 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
207 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
208 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
209 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
210 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
211 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
212 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
213 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
214 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
215 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
216 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
217 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
218 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
219 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
220 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
221 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
222 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
223 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
224 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
225 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
226 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
227 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
228 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
229 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
230 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
231 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
232 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
233 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
234 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
235 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
236 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
237 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
238 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
239 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
240 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
241 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
242 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
243 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
244 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
245 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
246 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
247 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
248 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
249 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
250 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
251 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
252 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
253 {
254 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
255 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
256 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
257 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
258 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
259 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
260 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
261 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
262 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
263 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
264 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
265 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
266 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
267 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
268 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
269 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
270 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
271 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
272 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
273 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
274 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
275 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
276 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
277 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
278 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
279 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
280 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
281 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
282 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
283 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
284 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
285 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
286 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
287 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
288 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
289 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
290 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
291 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
292 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
293 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
294 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
295 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
296 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
297 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
298 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
299 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
300 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
301 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
302 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
303 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
304 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
305 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
306 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
307 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
308 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
309 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
310 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
311 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
312 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
313 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
314 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
315 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
316 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
317 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
318 {
319 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
320 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
321 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
322 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
323 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
324 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
325 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
326 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
327 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
328 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
329 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
330 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
331 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
332 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
333 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
334 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
335 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
336 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
337 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
338 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
339 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
340 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
341 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
342 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
343 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
344 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
345 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
346 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
347 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
348 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
349 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
350 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
351 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
352 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
353 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
354 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
355 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
356 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
357 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
358 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
359 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
360 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
361 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
362 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
363 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
364 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
365 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
366 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
367 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
368 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
369 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
370 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
371 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
372 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
373 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
374 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
375 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
376 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
377 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
378 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
379 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
380 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
381 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
382 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
383 },
384 {
385 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
386 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
387 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
388 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
389 0x9216d5d9, 0x8979fb1b
390 } };
391
392 *c = initstate;
393}
394
395u_int32_t
396Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes,
397 u_int16_t *current)
398{
399 u_int8_t i;
400 u_int16_t j;
401 u_int32_t temp;
402
403 temp = 0x00000000;
404 j = *current;
405
406 for (i = 0; i < 4; i++, j++) {
407 if (j >= databytes)
408 j = 0;
409 temp = (temp << 8) | data[j];
410 }
411
412 *current = j;
413 return temp;
414}
415
416void
417Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)
418{
419 u_int16_t i;
420 u_int16_t j;
421 u_int16_t k;
422 u_int32_t temp;
423 u_int32_t datal;
424 u_int32_t datar;
425
426 j = 0;
427 for (i = 0; i < BLF_N + 2; i++) {
428 /* Extract 4 int8 to 1 int32 from keystream */
429 temp = Blowfish_stream2word(key, keybytes, &j);
430 c->P[i] = c->P[i] ^ temp;
431 }
432
433 j = 0;
434 datal = 0x00000000;
435 datar = 0x00000000;
436 for (i = 0; i < BLF_N + 2; i += 2) {
437 Blowfish_encipher(c, &datal, &datar);
438
439 c->P[i] = datal;
440 c->P[i + 1] = datar;
441 }
442
443 for (i = 0; i < 4; i++) {
444 for (k = 0; k < 256; k += 2) {
445 Blowfish_encipher(c, &datal, &datar);
446
447 c->S[i][k] = datal;
448 c->S[i][k + 1] = datar;
449 }
450 }
451}
452
453
454void
455Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,
456 const u_int8_t *key, u_int16_t keybytes)
457{
458 u_int16_t i;
459 u_int16_t j;
460 u_int16_t k;
461 u_int32_t temp;
462 u_int32_t datal;
463 u_int32_t datar;
464
465 j = 0;
466 for (i = 0; i < BLF_N + 2; i++) {
467 /* Extract 4 int8 to 1 int32 from keystream */
468 temp = Blowfish_stream2word(key, keybytes, &j);
469 c->P[i] = c->P[i] ^ temp;
470 }
471
472 j = 0;
473 datal = 0x00000000;
474 datar = 0x00000000;
475 for (i = 0; i < BLF_N + 2; i += 2) {
476 datal ^= Blowfish_stream2word(data, databytes, &j);
477 datar ^= Blowfish_stream2word(data, databytes, &j);
478 Blowfish_encipher(c, &datal, &datar);
479
480 c->P[i] = datal;
481 c->P[i + 1] = datar;
482 }
483
484 for (i = 0; i < 4; i++) {
485 for (k = 0; k < 256; k += 2) {
486 datal ^= Blowfish_stream2word(data, databytes, &j);
487 datar ^= Blowfish_stream2word(data, databytes, &j);
488 Blowfish_encipher(c, &datal, &datar);
489
490 c->S[i][k] = datal;
491 c->S[i][k + 1] = datar;
492 }
493 }
494
495}
496
497void
498blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)
499{
500 /* Initialize S-boxes and subkeys with Pi */
501 Blowfish_initstate(c);
502
503 /* Transform S-boxes and subkeys with key */
504 Blowfish_expand0state(c, k, len);
505}
506
507void
508blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
509{
510 u_int32_t *d;
511 u_int16_t i;
512
513 d = data;
514 for (i = 0; i < blocks; i++) {
515 Blowfish_encipher(c, d, d + 1);
516 d += 2;
517 }
518}
519
520void
521blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
522{
523 u_int32_t *d;
524 u_int16_t i;
525
526 d = data;
527 for (i = 0; i < blocks; i++) {
528 Blowfish_decipher(c, d, d + 1);
529 d += 2;
530 }
531}
532
533void
534blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
535{
536 u_int32_t l, r;
537 u_int32_t i;
538
539 for (i = 0; i < len; i += 8) {
540 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
541 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
542 Blowfish_encipher(c, &l, &r);
543 data[0] = l >> 24 & 0xff;
544 data[1] = l >> 16 & 0xff;
545 data[2] = l >> 8 & 0xff;
546 data[3] = l & 0xff;
547 data[4] = r >> 24 & 0xff;
548 data[5] = r >> 16 & 0xff;
549 data[6] = r >> 8 & 0xff;
550 data[7] = r & 0xff;
551 data += 8;
552 }
553}
554
555void
556blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
557{
558 u_int32_t l, r;
559 u_int32_t i;
560
561 for (i = 0; i < len; i += 8) {
562 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
563 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
564 Blowfish_decipher(c, &l, &r);
565 data[0] = l >> 24 & 0xff;
566 data[1] = l >> 16 & 0xff;
567 data[2] = l >> 8 & 0xff;
568 data[3] = l & 0xff;
569 data[4] = r >> 24 & 0xff;
570 data[5] = r >> 16 & 0xff;
571 data[6] = r >> 8 & 0xff;
572 data[7] = r & 0xff;
573 data += 8;
574 }
575}
576
577void
578blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)
579{
580 u_int32_t l, r;
581 u_int32_t i, j;
582
583 for (i = 0; i < len; i += 8) {
584 for (j = 0; j < 8; j++)
585 data[j] ^= iv[j];
586 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
587 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
588 Blowfish_encipher(c, &l, &r);
589 data[0] = l >> 24 & 0xff;
590 data[1] = l >> 16 & 0xff;
591 data[2] = l >> 8 & 0xff;
592 data[3] = l & 0xff;
593 data[4] = r >> 24 & 0xff;
594 data[5] = r >> 16 & 0xff;
595 data[6] = r >> 8 & 0xff;
596 data[7] = r & 0xff;
597 iv = data;
598 data += 8;
599 }
600}
601
602void
603blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)
604{
605 u_int32_t l, r;
606 u_int8_t *iv;
607 u_int32_t i, j;
608
609 iv = data + len - 16;
610 data = data + len - 8;
611 for (i = len - 8; i >= 8; i -= 8) {
612 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
613 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
614 Blowfish_decipher(c, &l, &r);
615 data[0] = l >> 24 & 0xff;
616 data[1] = l >> 16 & 0xff;
617 data[2] = l >> 8 & 0xff;
618 data[3] = l & 0xff;
619 data[4] = r >> 24 & 0xff;
620 data[5] = r >> 16 & 0xff;
621 data[6] = r >> 8 & 0xff;
622 data[7] = r & 0xff;
623 for (j = 0; j < 8; j++)
624 data[j] ^= iv[j];
625 iv -= 8;
626 data -= 8;
627 }
628 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
629 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
630 Blowfish_decipher(c, &l, &r);
631 data[0] = l >> 24 & 0xff;
632 data[1] = l >> 16 & 0xff;
633 data[2] = l >> 8 & 0xff;
634 data[3] = l & 0xff;
635 data[4] = r >> 24 & 0xff;
636 data[5] = r >> 16 & 0xff;
637 data[6] = r >> 8 & 0xff;
638 data[7] = r & 0xff;
639 for (j = 0; j < 8; j++)
640 data[j] ^= iva[j];
641}
642
643#if 0
644void
645report(u_int32_t data[], u_int16_t len)
646{
647 u_int16_t i;
648 for (i = 0; i < len; i += 2)
649 printf("Block %0hd: %08lx %08lx.\n",
650 i / 2, data[i], data[i + 1]);
651}
652void
653main(void)
654{
655
656 blf_ctx c;
657 char key[] = "AAAAA";
658 char key2[] = "abcdefghijklmnopqrstuvwxyz";
659
660 u_int32_t data[10];
661 u_int32_t data2[] =
662 {0x424c4f57l, 0x46495348l};
663
664 u_int16_t i;
665
666 /* First test */
667 for (i = 0; i < 10; i++)
668 data[i] = i;
669
670 blf_key(&c, (u_int8_t *) key, 5);
671 blf_enc(&c, data, 5);
672 blf_dec(&c, data, 1);
673 blf_dec(&c, data + 2, 4);
674 printf("Should read as 0 - 9.\n");
675 report(data, 10);
676
677 /* Second test */
678 blf_key(&c, (u_int8_t *) key2, strlen(key2));
679 blf_enc(&c, data2, 1);
680 printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
681 report(data2, 2);
682 blf_dec(&c, data2, 1);
683 report(data2, 2);
684}
685#endif
diff --git a/src/lib/libc/crypt/cast.c b/src/lib/libc/crypt/cast.c
new file mode 100644
index 0000000000..ea026638d6
--- /dev/null
+++ b/src/lib/libc/crypt/cast.c
@@ -0,0 +1,790 @@
1/* $OpenBSD: cast.c,v 1.3 2004/11/03 10:38:50 hshoexer Exp $ */
2/*
3 * CAST-128 in C
4 * Written by Steve Reid <sreid@sea-to-sky.net>
5 * 100% Public Domain - no warranty
6 * Released 1997.10.11
7 */
8
9#include <sys/types.h>
10
11#include <cast.h>
12
13/* CAST S-Boxes */
14
15static const u_int32_t cast_sbox1[256] = {
16 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A,
17 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949,
18 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675,
19 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E,
20 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2,
21 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D,
22 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F,
23 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0,
24 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE,
25 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7,
26 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F,
27 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935,
28 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D,
29 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D,
30 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165,
31 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50,
32 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272,
33 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE,
34 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D,
35 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3,
36 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A,
37 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167,
38 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F,
39 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291,
40 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9,
41 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779,
42 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6,
43 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2,
44 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9,
45 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511,
46 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E,
47 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D,
48 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E,
49 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5,
50 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82,
51 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324,
52 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC,
53 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C,
54 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F,
55 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC,
56 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491,
57 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D,
58 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE,
59 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96,
60 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A,
61 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A,
62 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79,
63 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D,
64 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779,
65 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD,
66 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755,
67 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6,
68 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB,
69 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9,
70 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0,
71 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872,
72 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79,
73 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C,
74 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298,
75 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E,
76 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571,
77 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9,
78 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D,
79 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF
80};
81
82static const u_int32_t cast_sbox2[256] = {
83 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380,
84 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651,
85 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,
86 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3,
87 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909,
88 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB,
89 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B,
90 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806,
91 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4,
92 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B,
93 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F,
94 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359,
95 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21,
96 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B,
97 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D,
98 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C,
99 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F,
100 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34,
101 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D,
102 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB,
103 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4,
104 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD,
105 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801,
106 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860,
107 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755,
108 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B,
109 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709,
110 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304,
111 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B,
112 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B,
113 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C,
114 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF,
115 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9,
116 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C,
117 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3,
118 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13,
119 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9,
120 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F,
121 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB,
122 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6,
123 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4,
124 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6,
125 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43,
126 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58,
127 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8,
128 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906,
129 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171,
130 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D,
131 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89,
132 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6,
133 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B,
134 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4,
135 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB,
136 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6,
137 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E,
138 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F,
139 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA,
140 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249,
141 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA,
142 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA,
143 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD,
144 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9,
145 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,
146 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1
147};
148
149static const u_int32_t cast_sbox3[256] = {
150 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907,
151 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90,
152 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,
153 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5,
154 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E,
155 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E,
156 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC,
157 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240,
158 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E,
159 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5,
160 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F,
161 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B,
162 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99,
163 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71,
164 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F,
165 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04,
166 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380,
167 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82,
168 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8,
169 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15,
170 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504,
171 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2,
172 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6,
173 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176,
174 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E,
175 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148,
176 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D,
177 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC,
178 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1,
179 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341,
180 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C,
181 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E,
182 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15,
183 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51,
184 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4,
185 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F,
186 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B,
187 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A,
188 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392,
189 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B,
190 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231,
191 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B,
192 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889,
193 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5,
194 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67,
195 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45,
196 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49,
197 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536,
198 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D,
199 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC,
200 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D,
201 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0,
202 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E,
203 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69,
204 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767,
205 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2,
206 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE,
207 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49,
208 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24,
209 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D,
210 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0,
211 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A,
212 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5,
213 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783
214};
215
216static const u_int32_t cast_sbox4[256] = {
217 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298,
218 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1,
219 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120,
220 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF,
221 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220,
222 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15,
223 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE,
224 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121,
225 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701,
226 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25,
227 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B,
228 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5,
229 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93,
230 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB,
231 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746,
232 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5,
233 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9,
234 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D,
235 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB,
236 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6,
237 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C,
238 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23,
239 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7,
240 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003,
241 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340,
242 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6,
243 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327,
244 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119,
245 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC,
246 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24,
247 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205,
248 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A,
249 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031,
250 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79,
251 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5,
252 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF,
253 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C,
254 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26,
255 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69,
256 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB,
257 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9,
258 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7,
259 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF,
260 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417,
261 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3,
262 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2,
263 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2,
264 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2,
265 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF,
266 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A,
267 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091,
268 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919,
269 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF,
270 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF,
271 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF,
272 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876,
273 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367,
274 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB,
275 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C,
276 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04,
277 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43,
278 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282,
279 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E,
280 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2
281};
282
283static const u_int32_t cast_sbox5[256] = {
284 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911,
285 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F,
286 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,
287 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A,
288 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180,
289 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,
290 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2,
291 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02,
292 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725,
293 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A,
294 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B,
295 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,
296 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571,
297 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9,
298 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC,
299 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981,
300 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA,
301 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774,
302 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263,
303 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655,
304 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468,
305 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2,
306 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B,
307 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,
308 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284,
309 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1,
310 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,
311 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA,
312 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7,
313 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049,
314 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE,
315 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F,
316 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,
317 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA,
318 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4,
319 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,
320 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561,
321 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3,
322 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,
323 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840,
324 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406,
325 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4,
326 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472,
327 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2,
328 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487,
329 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7,
330 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288,
331 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5,
332 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2,
333 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E,
334 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78,
335 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E,
336 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76,
337 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801,
338 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0,
339 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD,
340 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58,
341 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0,
342 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2,
343 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20,
344 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE,
345 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8,
346 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,
347 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4
348};
349
350static const u_int32_t cast_sbox6[256] = {
351 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C,
352 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC,
353 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
354 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138,
355 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E,
356 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367,
357 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866,
358 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98,
359 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C,
360 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072,
361 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD,
362 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,
363 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53,
364 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD,
365 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,
366 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8,
367 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF,
368 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,
369 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807,
370 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54,
371 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A,
372 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387,
373 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563,
374 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC,
375 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0,
376 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF,
377 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE,
378 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF,
379 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0,
380 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F,
381 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2,
382 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289,
383 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853,
384 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950,
385 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA,
386 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,
387 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9,
388 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B,
389 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751,
390 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE,
391 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358,
392 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,
393 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397,
394 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976,
395 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459,
396 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0,
397 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4,
398 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891,
399 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F,
400 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA,
401 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,
402 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC,
403 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2,
404 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,
405 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB,
406 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25,
407 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B,
408 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121,
409 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B,
410 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,
411 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855,
412 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD,
413 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,
414 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F
415};
416
417static const u_int32_t cast_sbox7[256] = {
418 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693,
419 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F,
420 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,
421 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE,
422 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD,
423 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,
424 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F,
425 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19,
426 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9,
427 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2,
428 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E,
429 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516,
430 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83,
431 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88,
432 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,
433 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816,
434 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A,
435 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756,
436 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F,
437 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A,
438 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B,
439 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264,
440 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78,
441 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,
442 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D,
443 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28,
444 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,
445 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3,
446 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9,
447 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7,
448 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302,
449 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06,
450 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858,
451 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033,
452 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A,
453 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A,
454 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4,
455 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566,
456 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,
457 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509,
458 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9,
459 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962,
460 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C,
461 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E,
462 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,
463 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C,
464 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939,
465 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,
466 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E,
467 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285,
468 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378,
469 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301,
470 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD,
471 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,
472 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567,
473 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767,
474 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,
475 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647,
476 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF,
477 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914,
478 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2,
479 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C,
480 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
481 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3
482};
483
484static const u_int32_t cast_sbox8[256] = {
485 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095,
486 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5,
487 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,
488 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC,
489 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940,
490 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,
491 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42,
492 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D,
493 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,
494 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2,
495 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4,
496 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862,
497 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0,
498 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC,
499 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6,
500 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C,
501 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491,
502 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E,
503 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B,
504 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039,
505 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,
506 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8,
507 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006,
508 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42,
509 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564,
510 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5,
511 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,
512 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472,
513 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC,
514 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225,
515 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8,
516 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C,
517 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,
518 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB,
519 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F,
520 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054,
521 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504,
522 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70,
523 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,
524 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC,
525 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6,
526 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,
527 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD,
528 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3,
529 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4,
530 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4,
531 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC,
532 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101,
533 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA,
534 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F,
535 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF,
536 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E,
537 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603,
538 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,
539 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37,
540 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C,
541 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,
542 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384,
543 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D,
544 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C,
545 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347,
546 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82,
547 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D,
548 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E
549};
550
551/* Macros to access 8-bit bytes out of a 32-bit word */
552#define U8a(x) ( (u_int8_t) (x>>24) )
553#define U8b(x) ( (u_int8_t) ((x>>16)&255) )
554#define U8c(x) ( (u_int8_t) ((x>>8)&255) )
555#define U8d(x) ( (u_int8_t) ((x)&255) )
556
557/* Circular left shift */
558#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) )
559
560/* CAST-128 uses three different round functions */
561#define F1(l, r, i) \
562 t = ROL(key->xkey[i] + r, key->xkey[i+16]); \
563 l ^= ((cast_sbox1[U8a(t)] ^ cast_sbox2[U8b(t)]) - \
564 cast_sbox3[U8c(t)]) + cast_sbox4[U8d(t)];
565#define F2(l, r, i) \
566 t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \
567 l ^= ((cast_sbox1[U8a(t)] - cast_sbox2[U8b(t)]) + \
568 cast_sbox3[U8c(t)]) ^ cast_sbox4[U8d(t)];
569#define F3(l, r, i) \
570 t = ROL(key->xkey[i] - r, key->xkey[i+16]); \
571 l ^= ((cast_sbox1[U8a(t)] + cast_sbox2[U8b(t)]) ^ \
572 cast_sbox3[U8c(t)]) - cast_sbox4[U8d(t)];
573
574
575/***** Encryption Function *****/
576
577void
578cast_encrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
579{
580 u_int32_t t, l, r;
581
582 /* Get inblock into l,r */
583 l = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
584 ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
585 r = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
586 ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
587 /* Do the work */
588 F1(l, r, 0);
589 F2(r, l, 1);
590 F3(l, r, 2);
591 F1(r, l, 3);
592 F2(l, r, 4);
593 F3(r, l, 5);
594 F1(l, r, 6);
595 F2(r, l, 7);
596 F3(l, r, 8);
597 F1(r, l, 9);
598 F2(l, r, 10);
599 F3(r, l, 11);
600 /* Only do full 16 rounds if key length > 80 bits */
601 if (key->rounds > 12) {
602 F1(l, r, 12);
603 F2(r, l, 13);
604 F3(l, r, 14);
605 F1(r, l, 15);
606 }
607 /* Put l,r into outblock */
608 outblock[0] = U8a(r);
609 outblock[1] = U8b(r);
610 outblock[2] = U8c(r);
611 outblock[3] = U8d(r);
612 outblock[4] = U8a(l);
613 outblock[5] = U8b(l);
614 outblock[6] = U8c(l);
615 outblock[7] = U8d(l);
616 /* Wipe clean */
617 t = l = r = 0;
618}
619
620
621/***** Decryption Function *****/
622
623void
624cast_decrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
625{
626 u_int32_t t, l, r;
627
628 /* Get inblock into l,r */
629 r = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
630 ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
631 l = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
632 ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
633 /* Do the work */
634 /* Only do full 16 rounds if key length > 80 bits */
635 if (key->rounds > 12) {
636 F1(r, l, 15);
637 F3(l, r, 14);
638 F2(r, l, 13);
639 F1(l, r, 12);
640 }
641 F3(r, l, 11);
642 F2(l, r, 10);
643 F1(r, l, 9);
644 F3(l, r, 8);
645 F2(r, l, 7);
646 F1(l, r, 6);
647 F3(r, l, 5);
648 F2(l, r, 4);
649 F1(r, l, 3);
650 F3(l, r, 2);
651 F2(r, l, 1);
652 F1(l, r, 0);
653 /* Put l,r into outblock */
654 outblock[0] = U8a(l);
655 outblock[1] = U8b(l);
656 outblock[2] = U8c(l);
657 outblock[3] = U8d(l);
658 outblock[4] = U8a(r);
659 outblock[5] = U8b(r);
660 outblock[6] = U8c(r);
661 outblock[7] = U8d(r);
662 /* Wipe clean */
663 t = l = r = 0;
664}
665
666
667/***** Key Schedual *****/
668
669void
670cast_setkey(cast_key* key, u_int8_t* rawkey, int keybytes)
671{
672 u_int32_t t[4], z[4], x[4];
673 int i;
674
675 /* Set number of rounds to 12 or 16, depending on key length */
676 key->rounds = (keybytes <= 10 ? 12 : 16);
677
678 /* Copy key to workspace x */
679 for (i = 0; i < 4; i++) {
680 x[i] = 0;
681 if ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24;
682 if ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16;
683 if ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8;
684 if ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3];
685 }
686 /* Generate 32 subkeys, four at a time */
687 for (i = 0; i < 32; i+=4) {
688 switch (i & 4) {
689 case 0:
690 t[0] = z[0] = x[0] ^ cast_sbox5[U8b(x[3])] ^
691 cast_sbox6[U8d(x[3])] ^ cast_sbox7[U8a(x[3])] ^
692 cast_sbox8[U8c(x[3])] ^ cast_sbox7[U8a(x[2])];
693 t[1] = z[1] = x[2] ^ cast_sbox5[U8a(z[0])] ^
694 cast_sbox6[U8c(z[0])] ^ cast_sbox7[U8b(z[0])] ^
695 cast_sbox8[U8d(z[0])] ^ cast_sbox8[U8c(x[2])];
696 t[2] = z[2] = x[3] ^ cast_sbox5[U8d(z[1])] ^
697 cast_sbox6[U8c(z[1])] ^ cast_sbox7[U8b(z[1])] ^
698 cast_sbox8[U8a(z[1])] ^ cast_sbox5[U8b(x[2])];
699 t[3] = z[3] = x[1] ^ cast_sbox5[U8c(z[2])] ^
700 cast_sbox6[U8b(z[2])] ^ cast_sbox7[U8d(z[2])] ^
701 cast_sbox8[U8a(z[2])] ^ cast_sbox6[U8d(x[2])];
702 break;
703 case 4:
704 t[0] = x[0] = z[2] ^ cast_sbox5[U8b(z[1])] ^
705 cast_sbox6[U8d(z[1])] ^ cast_sbox7[U8a(z[1])] ^
706 cast_sbox8[U8c(z[1])] ^ cast_sbox7[U8a(z[0])];
707 t[1] = x[1] = z[0] ^ cast_sbox5[U8a(x[0])] ^
708 cast_sbox6[U8c(x[0])] ^ cast_sbox7[U8b(x[0])] ^
709 cast_sbox8[U8d(x[0])] ^ cast_sbox8[U8c(z[0])];
710 t[2] = x[2] = z[1] ^ cast_sbox5[U8d(x[1])] ^
711 cast_sbox6[U8c(x[1])] ^ cast_sbox7[U8b(x[1])] ^
712 cast_sbox8[U8a(x[1])] ^ cast_sbox5[U8b(z[0])];
713 t[3] = x[3] = z[3] ^ cast_sbox5[U8c(x[2])] ^
714 cast_sbox6[U8b(x[2])] ^ cast_sbox7[U8d(x[2])] ^
715 cast_sbox8[U8a(x[2])] ^ cast_sbox6[U8d(z[0])];
716 break;
717 }
718 switch (i & 12) {
719 case 0:
720 case 12:
721 key->xkey[i+0] = cast_sbox5[U8a(t[2])] ^
722 cast_sbox6[U8b(t[2])] ^ cast_sbox7[U8d(t[1])] ^
723 cast_sbox8[U8c(t[1])];
724 key->xkey[i+1] = cast_sbox5[U8c(t[2])] ^
725 cast_sbox6[U8d(t[2])] ^ cast_sbox7[U8b(t[1])] ^
726 cast_sbox8[U8a(t[1])];
727 key->xkey[i+2] = cast_sbox5[U8a(t[3])] ^
728 cast_sbox6[U8b(t[3])] ^ cast_sbox7[U8d(t[0])] ^
729 cast_sbox8[U8c(t[0])];
730 key->xkey[i+3] = cast_sbox5[U8c(t[3])] ^
731 cast_sbox6[U8d(t[3])] ^ cast_sbox7[U8b(t[0])] ^
732 cast_sbox8[U8a(t[0])];
733 break;
734 case 4:
735 case 8:
736 key->xkey[i+0] = cast_sbox5[U8d(t[0])] ^
737 cast_sbox6[U8c(t[0])] ^ cast_sbox7[U8a(t[3])] ^
738 cast_sbox8[U8b(t[3])];
739 key->xkey[i+1] = cast_sbox5[U8b(t[0])] ^
740 cast_sbox6[U8a(t[0])] ^ cast_sbox7[U8c(t[3])] ^
741 cast_sbox8[U8d(t[3])];
742 key->xkey[i+2] = cast_sbox5[U8d(t[1])] ^
743 cast_sbox6[U8c(t[1])] ^ cast_sbox7[U8a(t[2])] ^
744 cast_sbox8[U8b(t[2])];
745 key->xkey[i+3] = cast_sbox5[U8b(t[1])] ^
746 cast_sbox6[U8a(t[1])] ^ cast_sbox7[U8c(t[2])] ^
747 cast_sbox8[U8d(t[2])];
748 break;
749 }
750 switch (i & 12) {
751 case 0:
752 key->xkey[i+0] ^= cast_sbox5[U8c(z[0])];
753 key->xkey[i+1] ^= cast_sbox6[U8c(z[1])];
754 key->xkey[i+2] ^= cast_sbox7[U8b(z[2])];
755 key->xkey[i+3] ^= cast_sbox8[U8a(z[3])];
756 break;
757 case 4:
758 key->xkey[i+0] ^= cast_sbox5[U8a(x[2])];
759 key->xkey[i+1] ^= cast_sbox6[U8b(x[3])];
760 key->xkey[i+2] ^= cast_sbox7[U8d(x[0])];
761 key->xkey[i+3] ^= cast_sbox8[U8d(x[1])];
762 break;
763 case 8:
764 key->xkey[i+0] ^= cast_sbox5[U8b(z[2])];
765 key->xkey[i+1] ^= cast_sbox6[U8a(z[3])];
766 key->xkey[i+2] ^= cast_sbox7[U8c(z[0])];
767 key->xkey[i+3] ^= cast_sbox8[U8c(z[1])];
768 break;
769 case 12:
770 key->xkey[i+0] ^= cast_sbox5[U8d(x[0])];
771 key->xkey[i+1] ^= cast_sbox6[U8d(x[1])];
772 key->xkey[i+2] ^= cast_sbox7[U8a(x[2])];
773 key->xkey[i+3] ^= cast_sbox8[U8b(x[3])];
774 break;
775 }
776 if (i >= 16) {
777 key->xkey[i+0] &= 31;
778 key->xkey[i+1] &= 31;
779 key->xkey[i+2] &= 31;
780 key->xkey[i+3] &= 31;
781 }
782 }
783 /* Wipe clean */
784 for (i = 0; i < 4; i++) {
785 t[i] = x[i] = z[i] = 0;
786 }
787}
788
789/* Made in Canada */
790
diff --git a/src/lib/libc/crypt/crypt.3 b/src/lib/libc/crypt/crypt.3
new file mode 100644
index 0000000000..2bc03fdd41
--- /dev/null
+++ b/src/lib/libc/crypt/crypt.3
@@ -0,0 +1,321 @@
1.\" $OpenBSD: crypt.3,v 1.23 2005/02/25 03:12:43 cloder Exp $
2.\"
3.\" FreeSec: libcrypt
4.\"
5.\" Copyright (c) 1994 David Burren
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.\" 4. Neither the name of the author nor the names of other 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 AUTHOR 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 AUTHOR 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.\" Manual page, using -mandoc macros
33.\"
34.Dd March 9, 1994
35.Dt CRYPT 3
36.Os
37.Sh NAME
38.Nm crypt ,
39.Nm setkey ,
40.Nm encrypt ,
41.Nm des_setkey ,
42.Nm des_cipher
43.Nd DES encryption
44.Sh SYNOPSIS
45.Fd #include <pwd.h>
46.Fd #include <unistd.h>
47.Ft char *
48.Fn crypt "const char *key" "const char *setting"
49.Ft int
50.Fn setkey "char *key"
51.Ft int
52.Fn encrypt "char *block" "int flag"
53.Ft int
54.Fn des_setkey "const char *key"
55.Ft int
56.Fn des_cipher "const char *in" "char *out" "int32_t salt" "int count"
57.Ft char *
58.Fn bcrypt_gensalt "u_int8_t log_rounds"
59.Ft char *
60.Fn bcrypt "const char *key" "const char *salt"
61.Ft char *
62.Fn md5crypt "const char *key" "const char *salt"
63.Sh DESCRIPTION
64The
65.Fn crypt
66function performs password encryption based on the
67.Tn NBS
68Data Encryption Standard (DES).
69Additional code has been added to deter key search attempts and to use
70stronger hashing algorithms.
71.Pp
72The first argument to
73.Fn crypt
74is a
75.Dv NUL Ns -terminated
76string, typically a user's typed password.
77The second is in one of three forms:
78if it begins with an underscore
79.Pq Ql _
80then an extended format is used
81in interpreting both the key and the setting, as outlined below.
82If it begins
83with a string character
84.Pq Ql $
85and a number then a different algorithm is used depending on the number.
86At the moment a
87.Ql $1
88chooses MD5 hashing and a
89.Ql $2
90chooses Blowfish hashing; see below for more information.
91.Ss Extended crypt
92The
93.Ar key
94is divided into groups of 8 characters (the last group is null-padded)
95and the low-order 7 bits of each character (56 bits per group) are
96used to form the DES key as follows:
97the first group of 56 bits becomes the initial DES key.
98For each additional group, the XOR of the encryption of the current DES
99key with itself and the group bits becomes the next DES key.
100.Pp
101The setting is a 9-character array consisting of an underscore followed
102by 4 bytes of iteration count and 4 bytes of salt.
103These are encoded as printable characters, 6 bits per character,
104least significant character first.
105The values 0 to 63 are encoded as
106.Dq \&./0-9A-Za-z .
107This allows 24 bits for both
108.Fa count
109and
110.Fa salt .
111.Ss "MD5" crypt
112For
113.Tn MD5
114crypt the version number,
115.Fa salt
116and the hashed password are separated by the
117.Ql $
118character.
119The maximum length of a password is limited by
120the length counter of the MD5 context, which is about
1212**64.
122A valid MD5 password entry looks like this:
123.Pp
124.Dq $1$caeiHQwX$hsKqOjrFRRN6K32OWkCBf1 .
125.Pp
126The whole MD5 password string is passed as
127.Fa setting
128for interpretation.
129.Ss "Blowfish" crypt
130The
131.Tn Blowfish
132version of crypt has 128 bits of
133.Fa salt
134in order to make building dictionaries of common passwords space consuming.
135The initial state of the
136.Tn Blowfish
137cipher is expanded using the
138.Fa salt
139and the
140.Fa password
141repeating the process a variable number of rounds, which is encoded in
142the password string.
143The maximum password length is 72.
144The final Blowfish password entry is created by encrypting the string
145.Pp
146.Dq OrpheanBeholderScryDoubt
147.Pp
148with the
149.Tn Blowfish
150state 64 times.
151.Pp
152The version number, the logarithm of the number of rounds and
153the concatenation of salt and hashed password are separated by the
154.Ql $
155character.
156An encoded
157.Sq 8
158would specify 256 rounds.
159A valid Blowfish password looks like this:
160.Pp
161.Dq $2a$12$eIAq8PR8sIUnJ1HaohxX2O9x9Qlm2vK97LJ5dsXdmB.eXF42qjchC .
162.Pp
163The whole Blowfish password string is passed as
164.Fa setting
165for interpretation.
166.Ss "Traditional" crypt
167The first 8 bytes of the key are null-padded, and the low-order 7 bits of
168each character is used to form the 56-bit
169.Tn DES
170key.
171.Pp
172The setting is a 2-character array of the ASCII-encoded salt.
173Thus only 12 bits of
174.Fa salt
175are used.
176.Fa count
177is set to 25.
178.Ss DES Algorithm
179The
180.Fa salt
181introduces disorder in the
182.Tn DES
183algorithm in one of 16777216 or 4096 possible ways
184(i.e., with 24 or 12 bits: if bit
185.Em i
186of the
187.Ar salt
188is set, then bits
189.Em i
190and
191.Em i+24
192are swapped in the
193.Tn DES
194E-box output).
195.Pp
196The DES key is used to encrypt a 64-bit constant using
197.Ar count
198iterations of
199.Tn DES .
200The value returned is a
201.Dv NUL Ns -terminated
202string, 20 or 13 bytes (plus NUL) in length, consisting of the
203.Ar setting
204followed by the encoded 64-bit encryption.
205.Pp
206The functions
207.Fn encrypt ,
208.Fn setkey ,
209.Fn des_setkey ,
210and
211.Fn des_cipher
212provide access to the
213.Tn DES
214algorithm itself.
215.Fn setkey
216is passed a 64-byte array of binary values (numeric 0 or 1).
217A 56-bit key is extracted from this array by dividing the
218array into groups of 8, and ignoring the last bit in each group.
219That bit is reserved for a byte parity check by DES, but is ignored
220by these functions.
221.Pp
222The
223.Fa block
224argument to
225.Fn encrypt
226is also a 64-byte array of binary values.
227If the value of
228.Fa flag
229is 0,
230.Fa block
231is encrypted otherwise it is decrypted.
232The result is returned in the original array
233.Fa block
234after using the key specified by
235.Fn setkey
236to process it.
237.Pp
238The argument to
239.Fn des_setkey
240is a character array of length 8.
241The least significant bit (the parity bit) in each character is ignored,
242and the remaining bits are concatenated to form a 56-bit key.
243The function
244.Fn des_cipher
245encrypts (or decrypts if
246.Fa count
247is negative) the 64-bits stored in the 8 characters at
248.Fa in
249using
250.Xr abs 3
251of
252.Fa count
253iterations of
254.Tn DES
255and stores the 64-bit result in the 8 characters at
256.Fa out
257(which may be the same as
258.Fa in ) .
259The
260.Fa salt
261specifies perturbations to the
262.Tn DES
263E-box output as described above.
264.Pp
265The function
266.Fn crypt
267returns a pointer to the encrypted value on success, and
268.Dv NULL
269on failure.
270The functions
271.Fn setkey ,
272.Fn encrypt ,
273.Fn des_setkey ,
274and
275.Fn des_cipher
276return 0 on success and 1 on failure.
277.Pp
278The
279.Fn crypt ,
280.Fn setkey ,
281and
282.Fn des_setkey
283functions all manipulate the same key space.
284.Sh SEE ALSO
285.Xr login 1 ,
286.Xr passwd 1 ,
287.Xr blowfish 3 ,
288.Xr getpass 3 ,
289.Xr md5 3 ,
290.Xr passwd 5
291.Sh HISTORY
292A rotor-based
293.Fn crypt
294function appeared in
295.At v3 .
296The current style
297.Fn crypt
298first appeared in
299.At v7 .
300.Pp
301This library (FreeSec 1.0) was developed outside the United States of America
302as an unencumbered replacement for the U.S.-only libcrypt encryption
303library.
304Programs linked against the
305.Fn crypt
306interface may be exported from the U.S.A. only if they use
307.Fn crypt
308solely for authentication purposes and avoid use of
309the other programmer interfaces listed above.
310Special care has been taken
311in the library so that programs which only use the
312.Fn crypt
313interface do not pull in the other components.
314.Sh AUTHORS
315.An David Burren Aq davidb@werj.com.au
316.Sh BUGS
317The
318.Fn crypt
319function returns a pointer to static data, and subsequent calls to
320.Fn crypt
321will modify the same object.
diff --git a/src/lib/libc/crypt/crypt.c b/src/lib/libc/crypt/crypt.c
new file mode 100644
index 0000000000..f0e2900f6d
--- /dev/null
+++ b/src/lib/libc/crypt/crypt.c
@@ -0,0 +1,700 @@
1/* $OpenBSD: crypt.c,v 1.19 2004/09/14 22:56:57 deraadt Exp $ */
2
3/*
4 * FreeSec: libcrypt
5 *
6 * Copyright (c) 1994 David Burren
7 * All rights reserved.
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 * 4. Neither the name of the author nor the names of other 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 AUTHOR 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 AUTHOR 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 * This is an original implementation of the DES and the crypt(3) interfaces
35 * by David Burren <davidb@werj.com.au>.
36 *
37 * An excellent reference on the underlying algorithm (and related
38 * algorithms) is:
39 *
40 * B. Schneier, Applied Cryptography: protocols, algorithms,
41 * and source code in C, John Wiley & Sons, 1994.
42 *
43 * Note that in that book's description of DES the lookups for the initial,
44 * pbox, and final permutations are inverted (this has been brought to the
45 * attention of the author). A list of errata for this book has been
46 * posted to the sci.crypt newsgroup by the author and is available for FTP.
47 */
48
49#if defined(LIBC_SCCS) && !defined(lint)
50static char rcsid[] = "$OpenBSD: crypt.c,v 1.19 2004/09/14 22:56:57 deraadt Exp $";
51#endif /* LIBC_SCCS and not lint */
52
53#include <sys/types.h>
54#include <sys/param.h>
55#include <pwd.h>
56#include <unistd.h>
57#include <string.h>
58
59#ifdef DEBUG
60# include <stdio.h>
61#endif
62
63static const u_char IP[64] = {
64 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
65 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
66 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
67 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
68};
69
70static u_char inv_key_perm[64];
71static u_char u_key_perm[56];
72static u_char const key_perm[56] = {
73 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
74 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
75 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
76 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
77};
78
79static const u_char key_shifts[16] = {
80 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
81};
82
83static u_char inv_comp_perm[56];
84static const u_char comp_perm[48] = {
85 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
86 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
87 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
88 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
89};
90
91/*
92 * No E box is used, as it's replaced by some ANDs, shifts, and ORs.
93 */
94
95static u_char u_sbox[8][64];
96static const u_char sbox[8][64] = {
97 {
98 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
99 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
100 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
101 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
102 },
103 {
104 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
105 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
106 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
107 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
108 },
109 {
110 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
111 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
112 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
113 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
114 },
115 {
116 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
117 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
118 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
119 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
120 },
121 {
122 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
123 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
124 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
125 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
126 },
127 {
128 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
129 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
130 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
131 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
132 },
133 {
134 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
135 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
136 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
137 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
138 },
139 {
140 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
141 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
142 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
143 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
144 }
145};
146
147static u_char un_pbox[32];
148static const u_char pbox[32] = {
149 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
150 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
151};
152
153const u_int32_t _des_bits32[32] =
154{
155 0x80000000, 0x40000000, 0x20000000, 0x10000000,
156 0x08000000, 0x04000000, 0x02000000, 0x01000000,
157 0x00800000, 0x00400000, 0x00200000, 0x00100000,
158 0x00080000, 0x00040000, 0x00020000, 0x00010000,
159 0x00008000, 0x00004000, 0x00002000, 0x00001000,
160 0x00000800, 0x00000400, 0x00000200, 0x00000100,
161 0x00000080, 0x00000040, 0x00000020, 0x00000010,
162 0x00000008, 0x00000004, 0x00000002, 0x00000001
163};
164
165const u_char _des_bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
166
167static u_int32_t saltbits;
168static int32_t old_salt;
169static const u_int32_t *bits28, *bits24;
170static u_char init_perm[64], final_perm[64];
171static u_int32_t en_keysl[16], en_keysr[16];
172static u_int32_t de_keysl[16], de_keysr[16];
173int _des_initialised = 0;
174static u_char m_sbox[4][4096];
175static u_int32_t psbox[4][256];
176static u_int32_t ip_maskl[8][256], ip_maskr[8][256];
177static u_int32_t fp_maskl[8][256], fp_maskr[8][256];
178static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128];
179static u_int32_t comp_maskl[8][128], comp_maskr[8][128];
180static u_int32_t old_rawkey0, old_rawkey1;
181
182static u_char ascii64[] =
183 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
184/* 0000000000111111111122222222223333333333444444444455555555556666 */
185/* 0123456789012345678901234567890123456789012345678901234567890123 */
186
187static __inline int
188ascii_to_bin(char ch)
189{
190 if (ch > 'z')
191 return(0);
192 if (ch >= 'a')
193 return(ch - 'a' + 38);
194 if (ch > 'Z')
195 return(0);
196 if (ch >= 'A')
197 return(ch - 'A' + 12);
198 if (ch > '9')
199 return(0);
200 if (ch >= '.')
201 return(ch - '.');
202 return(0);
203}
204
205void
206_des_init(void)
207{
208 int i, j, b, k, inbit, obit;
209 u_int32_t *p, *il, *ir, *fl, *fr;
210
211 old_rawkey0 = old_rawkey1 = 0;
212 saltbits = 0;
213 old_salt = 0;
214 bits24 = (bits28 = _des_bits32 + 4) + 4;
215
216 /*
217 * Invert the S-boxes, reordering the input bits.
218 */
219 for (i = 0; i < 8; i++)
220 for (j = 0; j < 64; j++) {
221 b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
222 u_sbox[i][j] = sbox[i][b];
223 }
224
225 /*
226 * Convert the inverted S-boxes into 4 arrays of 8 bits.
227 * Each will handle 12 bits of the S-box input.
228 */
229 for (b = 0; b < 4; b++)
230 for (i = 0; i < 64; i++)
231 for (j = 0; j < 64; j++)
232 m_sbox[b][(i << 6) | j] =
233 (u_sbox[(b << 1)][i] << 4) |
234 u_sbox[(b << 1) + 1][j];
235
236 /*
237 * Set up the initial & final permutations into a useful form, and
238 * initialise the inverted key permutation.
239 */
240 for (i = 0; i < 64; i++) {
241 init_perm[final_perm[i] = IP[i] - 1] = i;
242 inv_key_perm[i] = 255;
243 }
244
245 /*
246 * Invert the key permutation and initialise the inverted key
247 * compression permutation.
248 */
249 for (i = 0; i < 56; i++) {
250 u_key_perm[i] = key_perm[i] - 1;
251 inv_key_perm[key_perm[i] - 1] = i;
252 inv_comp_perm[i] = 255;
253 }
254
255 /*
256 * Invert the key compression permutation.
257 */
258 for (i = 0; i < 48; i++) {
259 inv_comp_perm[comp_perm[i] - 1] = i;
260 }
261
262 /*
263 * Set up the OR-mask arrays for the initial and final permutations,
264 * and for the key initial and compression permutations.
265 */
266 for (k = 0; k < 8; k++) {
267 for (i = 0; i < 256; i++) {
268 *(il = &ip_maskl[k][i]) = 0;
269 *(ir = &ip_maskr[k][i]) = 0;
270 *(fl = &fp_maskl[k][i]) = 0;
271 *(fr = &fp_maskr[k][i]) = 0;
272 for (j = 0; j < 8; j++) {
273 inbit = 8 * k + j;
274 if (i & _des_bits8[j]) {
275 if ((obit = init_perm[inbit]) < 32)
276 *il |= _des_bits32[obit];
277 else
278 *ir |= _des_bits32[obit-32];
279 if ((obit = final_perm[inbit]) < 32)
280 *fl |= _des_bits32[obit];
281 else
282 *fr |= _des_bits32[obit - 32];
283 }
284 }
285 }
286 for (i = 0; i < 128; i++) {
287 *(il = &key_perm_maskl[k][i]) = 0;
288 *(ir = &key_perm_maskr[k][i]) = 0;
289 for (j = 0; j < 7; j++) {
290 inbit = 8 * k + j;
291 if (i & _des_bits8[j + 1]) {
292 if ((obit = inv_key_perm[inbit]) == 255)
293 continue;
294 if (obit < 28)
295 *il |= bits28[obit];
296 else
297 *ir |= bits28[obit - 28];
298 }
299 }
300 *(il = &comp_maskl[k][i]) = 0;
301 *(ir = &comp_maskr[k][i]) = 0;
302 for (j = 0; j < 7; j++) {
303 inbit = 7 * k + j;
304 if (i & _des_bits8[j + 1]) {
305 if ((obit=inv_comp_perm[inbit]) == 255)
306 continue;
307 if (obit < 24)
308 *il |= bits24[obit];
309 else
310 *ir |= bits24[obit - 24];
311 }
312 }
313 }
314 }
315
316 /*
317 * Invert the P-box permutation, and convert into OR-masks for
318 * handling the output of the S-box arrays setup above.
319 */
320 for (i = 0; i < 32; i++)
321 un_pbox[pbox[i] - 1] = i;
322
323 for (b = 0; b < 4; b++)
324 for (i = 0; i < 256; i++) {
325 *(p = &psbox[b][i]) = 0;
326 for (j = 0; j < 8; j++) {
327 if (i & _des_bits8[j])
328 *p |= _des_bits32[un_pbox[8 * b + j]];
329 }
330 }
331
332 _des_initialised = 1;
333}
334
335void
336_des_setup_salt(int32_t salt)
337{
338 u_int32_t obit, saltbit;
339 int i;
340
341 if (salt == old_salt)
342 return;
343 old_salt = salt;
344
345 saltbits = 0;
346 saltbit = 1;
347 obit = 0x800000;
348 for (i = 0; i < 24; i++) {
349 if (salt & saltbit)
350 saltbits |= obit;
351 saltbit <<= 1;
352 obit >>= 1;
353 }
354}
355
356int
357des_setkey(const char *key)
358{
359 u_int32_t k0, k1, rawkey0, rawkey1;
360 int shifts, round;
361
362 if (!_des_initialised)
363 _des_init();
364
365 rawkey0 = ntohl(*(u_int32_t *) key);
366 rawkey1 = ntohl(*(u_int32_t *) (key + 4));
367
368 if ((rawkey0 | rawkey1)
369 && rawkey0 == old_rawkey0
370 && rawkey1 == old_rawkey1) {
371 /*
372 * Already setup for this key.
373 * This optimisation fails on a zero key (which is weak and
374 * has bad parity anyway) in order to simplify the starting
375 * conditions.
376 */
377 return(0);
378 }
379 old_rawkey0 = rawkey0;
380 old_rawkey1 = rawkey1;
381
382 /*
383 * Do key permutation and split into two 28-bit subkeys.
384 */
385 k0 = key_perm_maskl[0][rawkey0 >> 25]
386 | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
387 | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
388 | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
389 | key_perm_maskl[4][rawkey1 >> 25]
390 | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
391 | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
392 | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
393 k1 = key_perm_maskr[0][rawkey0 >> 25]
394 | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
395 | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
396 | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
397 | key_perm_maskr[4][rawkey1 >> 25]
398 | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
399 | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
400 | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
401 /*
402 * Rotate subkeys and do compression permutation.
403 */
404 shifts = 0;
405 for (round = 0; round < 16; round++) {
406 u_int32_t t0, t1;
407
408 shifts += key_shifts[round];
409
410 t0 = (k0 << shifts) | (k0 >> (28 - shifts));
411 t1 = (k1 << shifts) | (k1 >> (28 - shifts));
412
413 de_keysl[15 - round] =
414 en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
415 | comp_maskl[1][(t0 >> 14) & 0x7f]
416 | comp_maskl[2][(t0 >> 7) & 0x7f]
417 | comp_maskl[3][t0 & 0x7f]
418 | comp_maskl[4][(t1 >> 21) & 0x7f]
419 | comp_maskl[5][(t1 >> 14) & 0x7f]
420 | comp_maskl[6][(t1 >> 7) & 0x7f]
421 | comp_maskl[7][t1 & 0x7f];
422
423 de_keysr[15 - round] =
424 en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
425 | comp_maskr[1][(t0 >> 14) & 0x7f]
426 | comp_maskr[2][(t0 >> 7) & 0x7f]
427 | comp_maskr[3][t0 & 0x7f]
428 | comp_maskr[4][(t1 >> 21) & 0x7f]
429 | comp_maskr[5][(t1 >> 14) & 0x7f]
430 | comp_maskr[6][(t1 >> 7) & 0x7f]
431 | comp_maskr[7][t1 & 0x7f];
432 }
433 return(0);
434}
435
436int
437_des_do_des(u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out,
438 int count)
439{
440 /*
441 * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
442 */
443 u_int32_t l, r, *kl, *kr, *kl1, *kr1;
444 u_int32_t f, r48l, r48r;
445 int round;
446
447 if (count == 0) {
448 return(1);
449 } else if (count > 0) {
450 /*
451 * Encrypting
452 */
453 kl1 = en_keysl;
454 kr1 = en_keysr;
455 } else {
456 /*
457 * Decrypting
458 */
459 count = -count;
460 kl1 = de_keysl;
461 kr1 = de_keysr;
462 }
463
464 /*
465 * Do initial permutation (IP).
466 */
467 l = ip_maskl[0][l_in >> 24]
468 | ip_maskl[1][(l_in >> 16) & 0xff]
469 | ip_maskl[2][(l_in >> 8) & 0xff]
470 | ip_maskl[3][l_in & 0xff]
471 | ip_maskl[4][r_in >> 24]
472 | ip_maskl[5][(r_in >> 16) & 0xff]
473 | ip_maskl[6][(r_in >> 8) & 0xff]
474 | ip_maskl[7][r_in & 0xff];
475 r = ip_maskr[0][l_in >> 24]
476 | ip_maskr[1][(l_in >> 16) & 0xff]
477 | ip_maskr[2][(l_in >> 8) & 0xff]
478 | ip_maskr[3][l_in & 0xff]
479 | ip_maskr[4][r_in >> 24]
480 | ip_maskr[5][(r_in >> 16) & 0xff]
481 | ip_maskr[6][(r_in >> 8) & 0xff]
482 | ip_maskr[7][r_in & 0xff];
483
484 while (count--) {
485 /*
486 * Do each round.
487 */
488 kl = kl1;
489 kr = kr1;
490 round = 16;
491 while (round--) {
492 /*
493 * Expand R to 48 bits (simulate the E-box).
494 */
495 r48l = ((r & 0x00000001) << 23)
496 | ((r & 0xf8000000) >> 9)
497 | ((r & 0x1f800000) >> 11)
498 | ((r & 0x01f80000) >> 13)
499 | ((r & 0x001f8000) >> 15);
500
501 r48r = ((r & 0x0001f800) << 7)
502 | ((r & 0x00001f80) << 5)
503 | ((r & 0x000001f8) << 3)
504 | ((r & 0x0000001f) << 1)
505 | ((r & 0x80000000) >> 31);
506 /*
507 * Do salting for crypt() and friends, and
508 * XOR with the permuted key.
509 */
510 f = (r48l ^ r48r) & saltbits;
511 r48l ^= f ^ *kl++;
512 r48r ^= f ^ *kr++;
513 /*
514 * Do sbox lookups (which shrink it back to 32 bits)
515 * and do the pbox permutation at the same time.
516 */
517 f = psbox[0][m_sbox[0][r48l >> 12]]
518 | psbox[1][m_sbox[1][r48l & 0xfff]]
519 | psbox[2][m_sbox[2][r48r >> 12]]
520 | psbox[3][m_sbox[3][r48r & 0xfff]];
521 /*
522 * Now that we've permuted things, complete f().
523 */
524 f ^= l;
525 l = r;
526 r = f;
527 }
528 r = l;
529 l = f;
530 }
531 /*
532 * Do final permutation (inverse of IP).
533 */
534 *l_out = fp_maskl[0][l >> 24]
535 | fp_maskl[1][(l >> 16) & 0xff]
536 | fp_maskl[2][(l >> 8) & 0xff]
537 | fp_maskl[3][l & 0xff]
538 | fp_maskl[4][r >> 24]
539 | fp_maskl[5][(r >> 16) & 0xff]
540 | fp_maskl[6][(r >> 8) & 0xff]
541 | fp_maskl[7][r & 0xff];
542 *r_out = fp_maskr[0][l >> 24]
543 | fp_maskr[1][(l >> 16) & 0xff]
544 | fp_maskr[2][(l >> 8) & 0xff]
545 | fp_maskr[3][l & 0xff]
546 | fp_maskr[4][r >> 24]
547 | fp_maskr[5][(r >> 16) & 0xff]
548 | fp_maskr[6][(r >> 8) & 0xff]
549 | fp_maskr[7][r & 0xff];
550 return(0);
551}
552
553int
554des_cipher(const char *in, char *out, int32_t salt, int count)
555{
556 u_int32_t l_out, r_out, rawl, rawr;
557 u_int32_t x[2];
558 int retval;
559
560 if (!_des_initialised)
561 _des_init();
562
563 _des_setup_salt(salt);
564
565 memcpy(x, in, sizeof x);
566 rawl = ntohl(x[0]);
567 rawr = ntohl(x[1]);
568 retval = _des_do_des(rawl, rawr, &l_out, &r_out, count);
569
570 x[0] = htonl(l_out);
571 x[1] = htonl(r_out);
572 memcpy(out, x, sizeof x);
573 return(retval);
574}
575
576char *
577crypt(const char *key, const char *setting)
578{
579 int i;
580 u_int32_t count, salt, l, r0, r1, keybuf[2];
581 u_char *p, *q;
582 static u_char output[21];
583 extern char *md5crypt(const char *, const char *);
584 extern char *bcrypt(const char *, const char *);
585
586 if (setting[0] == '$') {
587 switch (setting[1]) {
588 case '1':
589 return (md5crypt(key, setting));
590 default:
591 return bcrypt(key, setting);
592 }
593 }
594
595 if (!_des_initialised)
596 _des_init();
597
598 /*
599 * Copy the key, shifting each character up by one bit
600 * and padding with zeros.
601 */
602 q = (u_char *) keybuf;
603 while ((q - (u_char *) keybuf) < sizeof(keybuf)) {
604 if ((*q++ = *key << 1))
605 key++;
606 }
607 if (des_setkey((char *) keybuf))
608 return(NULL);
609
610 if (*setting == _PASSWORD_EFMT1) {
611 /*
612 * "new"-style:
613 * setting - underscore, 4 bytes of count, 4 bytes of salt
614 * key - unlimited characters
615 */
616 for (i = 1, count = 0; i < 5; i++)
617 count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
618
619 for (i = 5, salt = 0; i < 9; i++)
620 salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
621
622 while (*key) {
623 /*
624 * Encrypt the key with itself.
625 */
626 if (des_cipher((char *)keybuf, (char *)keybuf, 0, 1))
627 return(NULL);
628 /*
629 * And XOR with the next 8 characters of the key.
630 */
631 q = (u_char *) keybuf;
632 while (((q - (u_char *) keybuf) < sizeof(keybuf)) &&
633 *key)
634 *q++ ^= *key++ << 1;
635
636 if (des_setkey((char *) keybuf))
637 return(NULL);
638 }
639 strlcpy((char *)output, setting, 10);
640
641 /*
642 * Double check that we weren't given a short setting.
643 * If we were, the above code will probably have created
644 * weird values for count and salt, but we don't really care.
645 * Just make sure the output string doesn't have an extra
646 * NUL in it.
647 */
648 p = output + strlen((const char *)output);
649 } else {
650 /*
651 * "old"-style:
652 * setting - 2 bytes of salt
653 * key - up to 8 characters
654 */
655 count = 25;
656
657 salt = (ascii_to_bin(setting[1]) << 6)
658 | ascii_to_bin(setting[0]);
659
660 output[0] = setting[0];
661 /*
662 * If the encrypted password that the salt was extracted from
663 * is only 1 character long, the salt will be corrupted. We
664 * need to ensure that the output string doesn't have an extra
665 * NUL in it!
666 */
667 output[1] = setting[1] ? setting[1] : output[0];
668
669 p = output + 2;
670 }
671 _des_setup_salt(salt);
672
673 /*
674 * Do it.
675 */
676 if (_des_do_des(0, 0, &r0, &r1, count))
677 return(NULL);
678 /*
679 * Now encode the result...
680 */
681 l = (r0 >> 8);
682 *p++ = ascii64[(l >> 18) & 0x3f];
683 *p++ = ascii64[(l >> 12) & 0x3f];
684 *p++ = ascii64[(l >> 6) & 0x3f];
685 *p++ = ascii64[l & 0x3f];
686
687 l = (r0 << 16) | ((r1 >> 16) & 0xffff);
688 *p++ = ascii64[(l >> 18) & 0x3f];
689 *p++ = ascii64[(l >> 12) & 0x3f];
690 *p++ = ascii64[(l >> 6) & 0x3f];
691 *p++ = ascii64[l & 0x3f];
692
693 l = r1 << 2;
694 *p++ = ascii64[(l >> 12) & 0x3f];
695 *p++ = ascii64[(l >> 6) & 0x3f];
696 *p++ = ascii64[l & 0x3f];
697 *p = 0;
698
699 return((char *)output);
700}
diff --git a/src/lib/libc/crypt/crypt2.c b/src/lib/libc/crypt/crypt2.c
new file mode 100644
index 0000000000..53b5bfb706
--- /dev/null
+++ b/src/lib/libc/crypt/crypt2.c
@@ -0,0 +1,108 @@
1/* $OpenBSD: crypt2.c,v 1.2 2004/09/14 22:56:57 deraadt Exp $ */
2
3/*
4 * FreeSec: libcrypt
5 *
6 * Copyright (c) 1994 David Burren
7 * All rights reserved.
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 * 4. Neither the name of the author nor the names of other 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 AUTHOR 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 AUTHOR 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 * This is an original implementation of the DES and the crypt(3) interfaces
35 * by David Burren <davidb@werj.com.au>.
36 *
37 * An excellent reference on the underlying algorithm (and related
38 * algorithms) is:
39 *
40 * B. Schneier, Applied Cryptography: protocols, algorithms,
41 * and source code in C, John Wiley & Sons, 1994.
42 *
43 * Note that in that book's description of DES the lookups for the initial,
44 * pbox, and final permutations are inverted (this has been brought to the
45 * attention of the author). A list of errata for this book has been
46 * posted to the sci.crypt newsgroup by the author and is available for FTP.
47 */
48
49#if defined(LIBC_SCCS) && !defined(lint)
50static char rcsid[] = "$OpenBSD: crypt2.c,v 1.2 2004/09/14 22:56:57 deraadt Exp $";
51#endif /* LIBC_SCCS and not lint */
52
53#include <sys/types.h>
54#include <sys/param.h>
55#include <pwd.h>
56#include <unistd.h>
57#include <string.h>
58
59#ifdef DEBUG
60# include <stdio.h>
61#endif
62
63extern const u_char _des_bits8[8];
64extern const u_int32_t _des_bits32[32];
65extern int _des_initialised;
66
67int
68setkey(const char *key)
69{
70 int i, j;
71 u_int32_t packed_keys[2];
72 u_char *p;
73
74 p = (u_char *) packed_keys;
75
76 for (i = 0; i < 8; i++) {
77 p[i] = 0;
78 for (j = 0; j < 8; j++)
79 if (*key++ & 1)
80 p[i] |= _des_bits8[j];
81 }
82 return(des_setkey((char *)p));
83}
84
85int
86encrypt(char *block, int flag)
87{
88 u_int32_t io[2];
89 u_char *p;
90 int i, j, retval;
91
92 if (!_des_initialised)
93 _des_init();
94
95 _des_setup_salt(0);
96 p = (u_char *)block;
97 for (i = 0; i < 2; i++) {
98 io[i] = 0L;
99 for (j = 0; j < 32; j++)
100 if (*p++ & 1)
101 io[i] |= _des_bits32[j];
102 }
103 retval = _des_do_des(io[0], io[1], io, io + 1, flag ? -1 : 1);
104 for (i = 0; i < 2; i++)
105 for (j = 0; j < 32; j++)
106 block[(i << 5) | j] = (io[i] & _des_bits32[j]) ? 1 : 0;
107 return(retval);
108}
diff --git a/src/lib/libc/crypt/md5crypt.c b/src/lib/libc/crypt/md5crypt.c
new file mode 100644
index 0000000000..97717e68d5
--- /dev/null
+++ b/src/lib/libc/crypt/md5crypt.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: md5crypt.c,v 1.13 2003/08/07 00:30:21 deraadt Exp $ */
2
3/*
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 *
11 * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
12 *
13 */
14
15#if defined(LIBC_SCCS) && !defined(lint)
16static char rcsid[] = "$OpenBSD: md5crypt.c,v 1.13 2003/08/07 00:30:21 deraadt Exp $";
17#endif /* LIBC_SCCS and not lint */
18
19#include <unistd.h>
20#include <stdio.h>
21#include <string.h>
22#include <md5.h>
23#include <string.h>
24
25static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
26 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
27
28static void to64(char *, u_int32_t, int);
29
30static void
31to64(char *s, u_int32_t v, int n)
32{
33 while (--n >= 0) {
34 *s++ = itoa64[v&0x3f];
35 v >>= 6;
36 }
37}
38
39/*
40 * UNIX password
41 *
42 * Use MD5 for what it is best at...
43 */
44
45char *md5crypt(const char *pw, const char *salt);
46
47char *
48md5crypt(const char *pw, const char *salt)
49{
50 /*
51 * This string is magic for this algorithm. Having
52 * it this way, we can get get better later on
53 */
54 static unsigned char *magic = (unsigned char *)"$1$";
55
56 static char passwd[120], *p;
57 static const unsigned char *sp,*ep;
58 unsigned char final[16];
59 int sl,pl,i;
60 MD5_CTX ctx,ctx1;
61 u_int32_t l;
62
63 /* Refine the Salt first */
64 sp = (const unsigned char *)salt;
65
66 /* If it starts with the magic string, then skip that */
67 if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
68 sp += strlen((const char *)magic);
69
70 /* It stops at the first '$', max 8 chars */
71 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
72 continue;
73
74 /* get the length of the true salt */
75 sl = ep - sp;
76
77 MD5Init(&ctx);
78
79 /* The password first, since that is what is most unknown */
80 MD5Update(&ctx,(const unsigned char *)pw,strlen(pw));
81
82 /* Then our magic string */
83 MD5Update(&ctx,magic,strlen((const char *)magic));
84
85 /* Then the raw salt */
86 MD5Update(&ctx,sp,sl);
87
88 /* Then just as many characters of the MD5(pw,salt,pw) */
89 MD5Init(&ctx1);
90 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
91 MD5Update(&ctx1,sp,sl);
92 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
93 MD5Final(final,&ctx1);
94 for(pl = strlen(pw); pl > 0; pl -= 16)
95 MD5Update(&ctx,final,pl>16 ? 16 : pl);
96
97 /* Don't leave anything around in vm they could use. */
98 memset(final,0,sizeof final);
99
100 /* Then something really weird... */
101 for (i = strlen(pw); i ; i >>= 1)
102 if(i&1)
103 MD5Update(&ctx, final, 1);
104 else
105 MD5Update(&ctx, (const unsigned char *)pw, 1);
106
107 /* Now make the output string */
108 snprintf(passwd, sizeof(passwd), "%s%.*s$", (char *)magic,
109 sl, (const char *)sp);
110
111 MD5Final(final,&ctx);
112
113 /*
114 * and now, just to make sure things don't run too fast
115 * On a 60 Mhz Pentium this takes 34 msec, so you would
116 * need 30 seconds to build a 1000 entry dictionary...
117 */
118 for(i=0;i<1000;i++) {
119 MD5Init(&ctx1);
120 if(i & 1)
121 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
122 else
123 MD5Update(&ctx1,final,16);
124
125 if(i % 3)
126 MD5Update(&ctx1,sp,sl);
127
128 if(i % 7)
129 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
130
131 if(i & 1)
132 MD5Update(&ctx1,final,16);
133 else
134 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
135 MD5Final(final,&ctx1);
136 }
137
138 p = passwd + strlen(passwd);
139
140 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
141 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
142 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
143 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
144 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
145 l = final[11] ; to64(p,l,2); p += 2;
146 *p = '\0';
147
148 /* Don't leave anything around in vm they could use. */
149 memset(final, 0, sizeof final);
150
151 return passwd;
152}
153
diff --git a/src/lib/libc/crypt/skipjack.c b/src/lib/libc/crypt/skipjack.c
new file mode 100644
index 0000000000..2212b984bb
--- /dev/null
+++ b/src/lib/libc/crypt/skipjack.c
@@ -0,0 +1,260 @@
1/* $OpenBSD: skipjack.c,v 1.3 2004/10/01 04:08:45 jsg Exp $ */
2
3/*
4 * Further optimized test implementation of SKIPJACK algorithm
5 * Mark Tillotson <markt@chaos.org.uk>, 25 June 98
6 * Optimizations suit RISC (lots of registers) machine best.
7 *
8 * based on unoptimized implementation of
9 * Panu Rissanen <bande@lut.fi> 960624
10 *
11 * SKIPJACK and KEA Algorithm Specifications
12 * Version 2.0
13 * 29 May 1998
14*/
15
16#include <sys/param.h>
17#include <skipjack.h>
18#include <stdlib.h>
19
20static const u_int8_t ftable[0x100] =
21{
22 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,
23 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
24 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,
25 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
26 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,
27 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
28 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,
29 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
30 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,
31 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
32 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,
33 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
34 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,
35 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
36 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,
37 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
38 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,
39 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
40 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,
41 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
42 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,
43 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
44 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,
45 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
46 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,
47 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
48 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,
49 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
50 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,
51 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
52 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,
53 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
54};
55
56/*
57 * For each key byte generate a table to represent the function
58 * ftable [in ^ keybyte]
59 *
60 * These tables used to save an XOR in each stage of the G-function
61 * the tables are hopefully pointed to by register allocated variables
62 * k0, k1..k9
63 */
64void
65subkey_table_gen (u_int8_t *key, u_int8_t **key_tables)
66{
67 int i, k;
68
69 for (k = 0; k < 10; k++) {
70 u_int8_t key_byte = key[k];
71 u_int8_t * table = (u_int8_t *) malloc(0x100);
72 /* XXX */
73
74 key_tables[k] = table;
75 for (i = 0; i < 0x100; i++)
76 table[i] = ftable[i ^ key_byte];
77 }
78}
79
80
81#define g(k0, k1, k2, k3, ih, il, oh, ol) \
82{ \
83 oh = k##k0 [il] ^ ih; \
84 ol = k##k1 [oh] ^ il; \
85 oh = k##k2 [ol] ^ oh; \
86 ol = k##k3 [oh] ^ ol; \
87}
88
89#define g0(ih, il, oh, ol) g(0, 1, 2, 3, ih, il, oh, ol)
90#define g4(ih, il, oh, ol) g(4, 5, 6, 7, ih, il, oh, ol)
91#define g8(ih, il, oh, ol) g(8, 9, 0, 1, ih, il, oh, ol)
92#define g2(ih, il, oh, ol) g(2, 3, 4, 5, ih, il, oh, ol)
93#define g6(ih, il, oh, ol) g(6, 7, 8, 9, ih, il, oh, ol)
94
95
96#define g_inv(k0, k1, k2, k3, ih, il, oh, ol) \
97{ \
98 ol = k##k3 [ih] ^ il; \
99 oh = k##k2 [ol] ^ ih; \
100 ol = k##k1 [oh] ^ ol; \
101 oh = k##k0 [ol] ^ oh; \
102}
103
104
105#define g0_inv(ih, il, oh, ol) g_inv(0, 1, 2, 3, ih, il, oh, ol)
106#define g4_inv(ih, il, oh, ol) g_inv(4, 5, 6, 7, ih, il, oh, ol)
107#define g8_inv(ih, il, oh, ol) g_inv(8, 9, 0, 1, ih, il, oh, ol)
108#define g2_inv(ih, il, oh, ol) g_inv(2, 3, 4, 5, ih, il, oh, ol)
109#define g6_inv(ih, il, oh, ol) g_inv(6, 7, 8, 9, ih, il, oh, ol)
110
111/* optimized version of Skipjack algorithm
112 *
113 * the appropriate g-function is inlined for each round
114 *
115 * the data movement is minimized by rotating the names of the
116 * variables w1..w4, not their contents (saves 3 moves per round)
117 *
118 * the loops are completely unrolled (needed to staticize choice of g)
119 *
120 * compiles to about 470 instructions on a Sparc (gcc -O)
121 * which is about 58 instructions per byte, 14 per round.
122 * gcc seems to leave in some unnecessary and with 0xFF operations
123 * but only in the latter part of the functions. Perhaps it
124 * runs out of resources to properly optimize long inlined function?
125 * in theory should get about 11 instructions per round, not 14
126 */
127
128void
129skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key_tables)
130{
131 u_int8_t wh1 = plain[0]; u_int8_t wl1 = plain[1];
132 u_int8_t wh2 = plain[2]; u_int8_t wl2 = plain[3];
133 u_int8_t wh3 = plain[4]; u_int8_t wl3 = plain[5];
134 u_int8_t wh4 = plain[6]; u_int8_t wl4 = plain[7];
135
136 u_int8_t * k0 = key_tables [0];
137 u_int8_t * k1 = key_tables [1];
138 u_int8_t * k2 = key_tables [2];
139 u_int8_t * k3 = key_tables [3];
140 u_int8_t * k4 = key_tables [4];
141 u_int8_t * k5 = key_tables [5];
142 u_int8_t * k6 = key_tables [6];
143 u_int8_t * k7 = key_tables [7];
144 u_int8_t * k8 = key_tables [8];
145 u_int8_t * k9 = key_tables [9];
146
147 /* first 8 rounds */
148 g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 1; wh4 ^= wh1;
149 g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 2; wh3 ^= wh4;
150 g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 3; wh2 ^= wh3;
151 g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 4; wh1 ^= wh2;
152 g6 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 5; wh4 ^= wh1;
153 g0 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 6; wh3 ^= wh4;
154 g4 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 7; wh2 ^= wh3;
155 g8 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 8; wh1 ^= wh2;
156
157 /* second 8 rounds */
158 wh2 ^= wh1; wl2 ^= wl1 ^ 9 ; g2 (wh1,wl1, wh1,wl1);
159 wh1 ^= wh4; wl1 ^= wl4 ^ 10; g6 (wh4,wl4, wh4,wl4);
160 wh4 ^= wh3; wl4 ^= wl3 ^ 11; g0 (wh3,wl3, wh3,wl3);
161 wh3 ^= wh2; wl3 ^= wl2 ^ 12; g4 (wh2,wl2, wh2,wl2);
162 wh2 ^= wh1; wl2 ^= wl1 ^ 13; g8 (wh1,wl1, wh1,wl1);
163 wh1 ^= wh4; wl1 ^= wl4 ^ 14; g2 (wh4,wl4, wh4,wl4);
164 wh4 ^= wh3; wl4 ^= wl3 ^ 15; g6 (wh3,wl3, wh3,wl3);
165 wh3 ^= wh2; wl3 ^= wl2 ^ 16; g0 (wh2,wl2, wh2,wl2);
166
167 /* third 8 rounds */
168 g4 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 17; wh4 ^= wh1;
169 g8 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 18; wh3 ^= wh4;
170 g2 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 19; wh2 ^= wh3;
171 g6 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 20; wh1 ^= wh2;
172 g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 21; wh4 ^= wh1;
173 g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 22; wh3 ^= wh4;
174 g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 23; wh2 ^= wh3;
175 g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 24; wh1 ^= wh2;
176
177 /* last 8 rounds */
178 wh2 ^= wh1; wl2 ^= wl1 ^ 25; g6 (wh1,wl1, wh1,wl1);
179 wh1 ^= wh4; wl1 ^= wl4 ^ 26; g0 (wh4,wl4, wh4,wl4);
180 wh4 ^= wh3; wl4 ^= wl3 ^ 27; g4 (wh3,wl3, wh3,wl3);
181 wh3 ^= wh2; wl3 ^= wl2 ^ 28; g8 (wh2,wl2, wh2,wl2);
182 wh2 ^= wh1; wl2 ^= wl1 ^ 29; g2 (wh1,wl1, wh1,wl1);
183 wh1 ^= wh4; wl1 ^= wl4 ^ 30; g6 (wh4,wl4, wh4,wl4);
184 wh4 ^= wh3; wl4 ^= wl3 ^ 31; g0 (wh3,wl3, wh3,wl3);
185 wh3 ^= wh2; wl3 ^= wl2 ^ 32; g4 (wh2,wl2, wh2,wl2);
186
187 /* pack into byte vector */
188 cipher [0] = wh1; cipher [1] = wl1;
189 cipher [2] = wh2; cipher [3] = wl2;
190 cipher [4] = wh3; cipher [5] = wl3;
191 cipher [6] = wh4; cipher [7] = wl4;
192}
193
194
195void
196skipjack_backwards (u_int8_t *cipher, u_int8_t *plain, u_int8_t **key_tables)
197{
198 /* setup 4 16-bit portions */
199 u_int8_t wh1 = cipher[0]; u_int8_t wl1 = cipher[1];
200 u_int8_t wh2 = cipher[2]; u_int8_t wl2 = cipher[3];
201 u_int8_t wh3 = cipher[4]; u_int8_t wl3 = cipher[5];
202 u_int8_t wh4 = cipher[6]; u_int8_t wl4 = cipher[7];
203
204 u_int8_t * k0 = key_tables [0];
205 u_int8_t * k1 = key_tables [1];
206 u_int8_t * k2 = key_tables [2];
207 u_int8_t * k3 = key_tables [3];
208 u_int8_t * k4 = key_tables [4];
209 u_int8_t * k5 = key_tables [5];
210 u_int8_t * k6 = key_tables [6];
211 u_int8_t * k7 = key_tables [7];
212 u_int8_t * k8 = key_tables [8];
213 u_int8_t * k9 = key_tables [9];
214
215 /* first 8 rounds */
216 g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 32; wh3 ^= wh2;
217 g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 31; wh4 ^= wh3;
218 g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 30; wh1 ^= wh4;
219 g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 29; wh2 ^= wh1;
220 g8_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 28; wh3 ^= wh2;
221 g4_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 27; wh4 ^= wh3;
222 g0_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 26; wh1 ^= wh4;
223 g6_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 25; wh2 ^= wh1;
224
225 /* second 8 rounds */
226 wh1 ^= wh2; wl1 ^= wl2 ^ 24; g2_inv (wh2,wl2, wh2,wl2);
227 wh2 ^= wh3; wl2 ^= wl3 ^ 23; g8_inv (wh3,wl3, wh3,wl3);
228 wh3 ^= wh4; wl3 ^= wl4 ^ 22; g4_inv (wh4,wl4, wh4,wl4);
229 wh4 ^= wh1; wl4 ^= wl1 ^ 21; g0_inv (wh1,wl1, wh1,wl1);
230 wh1 ^= wh2; wl1 ^= wl2 ^ 20; g6_inv (wh2,wl2, wh2,wl2);
231 wh2 ^= wh3; wl2 ^= wl3 ^ 19; g2_inv (wh3,wl3, wh3,wl3);
232 wh3 ^= wh4; wl3 ^= wl4 ^ 18; g8_inv (wh4,wl4, wh4,wl4);
233 wh4 ^= wh1; wl4 ^= wl1 ^ 17; g4_inv (wh1,wl1, wh1,wl1);
234
235 /* third 8 rounds */
236 g0_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 16; wh3 ^= wh2;
237 g6_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 15; wh4 ^= wh3;
238 g2_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 14; wh1 ^= wh4;
239 g8_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 13; wh2 ^= wh1;
240 g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 12; wh3 ^= wh2;
241 g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 11; wh4 ^= wh3;
242 g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 10; wh1 ^= wh4;
243 g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 9; wh2 ^= wh1;
244
245 /* last 8 rounds */
246 wh1 ^= wh2; wl1 ^= wl2 ^ 8; g8_inv (wh2,wl2, wh2,wl2);
247 wh2 ^= wh3; wl2 ^= wl3 ^ 7; g4_inv (wh3,wl3, wh3,wl3);
248 wh3 ^= wh4; wl3 ^= wl4 ^ 6; g0_inv (wh4,wl4, wh4,wl4);
249 wh4 ^= wh1; wl4 ^= wl1 ^ 5; g6_inv (wh1,wl1, wh1,wl1);
250 wh1 ^= wh2; wl1 ^= wl2 ^ 4; g2_inv (wh2,wl2, wh2,wl2);
251 wh2 ^= wh3; wl2 ^= wl3 ^ 3; g8_inv (wh3,wl3, wh3,wl3);
252 wh3 ^= wh4; wl3 ^= wl4 ^ 2; g4_inv (wh4,wl4, wh4,wl4);
253 wh4 ^= wh1; wl4 ^= wl1 ^ 1; g0_inv (wh1,wl1, wh1,wl1);
254
255 /* pack into byte vector */
256 plain [0] = wh1; plain [1] = wl1;
257 plain [2] = wh2; plain [3] = wl2;
258 plain [4] = wh3; plain [5] = wl3;
259 plain [6] = wh4; plain [7] = wl4;
260}
diff --git a/src/lib/libc/include/namespace.h b/src/lib/libc/include/namespace.h
new file mode 100644
index 0000000000..4a51f15ddf
--- /dev/null
+++ b/src/lib/libc/include/namespace.h
@@ -0,0 +1,18 @@
1/* $OpenBSD: namespace.h,v 1.2 1996/08/19 08:28:08 tholo Exp $ */
2
3#define catclose _catclose
4#define catgets _catgets
5#define catopen _catopen
6#define err _err
7#define errx _errx
8#define strtoq _strtoq
9#define strtouq _strtouq
10#define sys_errlist _sys_errlist
11#define sys_nerr _sys_nerr
12#define sys_siglist _sys_siglist
13#define verr _verr
14#define verrx _verrx
15#define vwarn _vwarn
16#define vwarnx _vwarnx
17#define warn _warn
18#define warnx _warnx
diff --git a/src/lib/libc/include/thread_private.h b/src/lib/libc/include/thread_private.h
new file mode 100644
index 0000000000..edac6b008d
--- /dev/null
+++ b/src/lib/libc/include/thread_private.h
@@ -0,0 +1,126 @@
1/* $OpenBSD: thread_private.h,v 1.16 2004/06/07 21:11:23 marc Exp $ */
2
3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
4
5#ifndef _THREAD_PRIVATE_H_
6#define _THREAD_PRIVATE_H_
7
8/*
9 * This file defines the thread library interface to libc. Thread
10 * libraries must implement the functions described here for proper
11 * inter-operation with libc. libc contains weak versions of the
12 * described functions for operation in a non-threaded environment.
13 */
14
15/*
16 * This variable is 0 until a second thread is created.
17 */
18extern int __isthreaded;
19
20/*
21 * Weak symbols are used in libc so that the thread library can
22 * efficiently wrap libc functions.
23 *
24 * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n),
25 * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n,
26 * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n).
27 */
28#define WEAK_NAME(name) __CONCAT(_weak_,name)
29#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
30#ifdef __GNUC__
31#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
32#else
33#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
34#endif
35
36/*
37 * helper macro to make unique names in the thread namespace
38 */
39#define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name)
40
41/*
42 * helper functions that exist as (weak) null functions in libc and
43 * (strong) functions in the thread library. These functions:
44 *
45 * _thread_tag_lock:
46 * lock the mutex associated with the given tag. If the given
47 * tag is NULL a tag is first allocated.
48 *
49 * _thread_tag_unlock:
50 * unlock the mutex associated with the given tag. If the given
51 * tag is NULL a tag is first allocated.
52 *
53 * _thread_tag_storage:
54 * return a pointer to per thread instance of data associated
55 * with the given tag. If the given tag is NULL a tag is first
56 * allocated.
57 */
58void _thread_tag_lock(void **);
59void _thread_tag_unlock(void **);
60void *_thread_tag_storage(void **, void *, size_t, void *);
61
62/*
63 * Macros used in libc to access thread mutex, keys, and per thread storage.
64 * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for
65 * historical reasons. They do the same thing, define a static variable
66 * keyed by 'name' that identifies a mutex and a key to identify per thread
67 * data.
68 */
69#define _THREAD_PRIVATE_KEY(name) \
70 static void *__THREAD_NAME(name)
71#define _THREAD_PRIVATE_MUTEX(name) \
72 static void *__THREAD_NAME(name)
73#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
74 _thread_tag_lock(&(__THREAD_NAME(name)))
75#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
76 _thread_tag_unlock(&(__THREAD_NAME(name)))
77#define _THREAD_PRIVATE(keyname, storage, error) \
78 _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \
79 sizeof (storage), error)
80/*
81 * Resolver code is special cased in that it uses global keys.
82 */
83extern void *__THREAD_NAME(_res);
84extern void *__THREAD_NAME(_res_ext);
85extern void *__THREAD_NAME(serv_mutex);
86
87/*
88 * File descriptor locking definitions.
89 */
90#define FD_READ 0x1
91#define FD_WRITE 0x2
92#define FD_RDWR (FD_READ | FD_WRITE)
93
94int _thread_fd_lock(int, int, struct timespec *);
95void _thread_fd_unlock(int, int);
96
97/*
98 * Macros are used in libc code for historical (debug) reasons.
99 * Define them here.
100 */
101#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
102#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
103
104
105/*
106 * malloc lock/unlock prototypes and definitions
107 */
108void _thread_malloc_init(void);
109void _thread_malloc_lock(void);
110void _thread_malloc_unlock(void);
111
112#define _MALLOC_LOCK() do { \
113 if (__isthreaded) \
114 _thread_malloc_lock(); \
115 } while (0)
116#define _MALLOC_UNLOCK() do { \
117 if (__isthreaded) \
118 _thread_malloc_unlock();\
119 } while (0)
120#define _MALLOC_LOCK_INIT() do { \
121 if (__isthreaded) \
122 _thread_malloc_init();\
123 } while (0)
124
125
126#endif /* _THREAD_PRIVATE_H_ */
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
new file mode 100644
index 0000000000..6b7740195f
--- /dev/null
+++ b/src/lib/libc/net/Makefile.inc
@@ -0,0 +1,92 @@
1# $OpenBSD: Makefile.inc,v 1.39 2005/01/06 04:24:14 itojun Exp $
2
3# net sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
5
6CFLAGS+=-DRESOLVSORT
7
8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \
9 getifaddrs.c getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \
10 getnetnamadr.c getproto.c getprotoent.c getprotoname.c \
11 getservbyname.c getservbyport.c getservent.c getrrsetbyname.c \
12 herror.c if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \
13 inet_lnaof.c inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \
14 inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c inet_pton.c \
15 ipx_addr.c ipx_ntoa.c linkaddr.c ns_addr.c ns_ntoa.c \
16 nsap_addr.c \
17 net_addrcmp.c \
18 rcmd.c rresvport.c recv.c res_comp.c res_data.c res_debug.c \
19 res_init.c res_mkquery.c res_query.c res_random.c res_send.c send.c \
20 sethostent.c ethers.c rcmdsh.c
21
22# IPv6
23SRCS+= ip6opt.c rthdr.c vars6.c
24
25# machine-dependent net sources
26# m-d Makefile.inc must include sources for:
27# htonl() htons() ntohl() ntohs()
28
29.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
30
31MAN+= byteorder.3 ethers.3 gai_strerror.3 getaddrinfo.3 gethostbyname.3 \
32 getifaddrs.3 getnameinfo.3 getnetent.3 getprotoent.3 \
33 getrrsetbyname.3 getservent.3 if_indextoname.3 inet.3 \
34 inet_net.3 inet6_option_space.3 inet6_rthdr_space.3 \
35 ipx.3 link_addr.3 net_addrcmp.3 ns.3 \
36 rcmd.3 rcmdsh.3 resolver.3
37
38MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
39 byteorder.3 ntohs.3 byteorder.3 htobe16.3 byteorder.3 htobe32.3 \
40 byteorder.3 htobe64.3 byteorder.3 betoh16.3 byteorder.3 betoh32.3 \
41 byteorder.3 betoh64.3 byteorder.3 htole16.3 byteorder.3 htole32.3 \
42 byteorder.3 htole64.3 byteorder.3 letoh16.3 byteorder.3 letoh32.3 \
43 byteorder.3 letoh64.3 byteorder.3 swap16.3 byteorder.3 swap32.3 \
44 byteorder.3 swap64.3
45MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
46 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 ethers.3 ether_addr.3
47MLINKS+=getaddrinfo.3 freeaddrinfo.3
48MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
49 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
50 gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3 \
51 gethostbyname.3 hstrerror.3
52MLINKS+=getifaddrs.3 freeifaddrs.3
53MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
54 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
55MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
56 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 \
57 getprotoent.3 getprotoent_r.3 getprotoent.3 getprotobyname_r.3 \
58 getprotoent.3 getprotobynumber_r.3 getprotoent.3 setprotoent_r.3 \
59 getprotoent.3 endprotoent_r.3
60MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
61 getservent.3 getservbyport.3 getservent.3 setservent.3 \
62 getservent.3 getservent_r.3 getservent.3 getservbyname_r.3 \
63 getservent.3 getservbyport_r.3 setservent.3 setservent_r.3 \
64 setservent.3 endservent_r.3
65MLINKS+= if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
66 if_indextoname.3 if_freenameindex.3
67MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
68 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
69 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \
70 inet.3 ntoa.3 inet.3 inet_ntop.3 inet.3 inet_pton.3
71MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
72MLINKS+=link_addr.3 link_ntoa.3
73MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
74MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
75MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
76 rcmd.3 rresvport_af.3 rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3
77MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
78 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
79 resolver.3 res_search.3
80MLINKS+=getrrsetbyname.3 freerrset.3
81MLINKS+=inet6_option_space.3 inet6_option_init.3 \
82 inet6_option_space.3 inet6_option_append.3 \
83 inet6_option_space.3 inet6_option_alloc.3 \
84 inet6_option_space.3 inet6_option_next.3 \
85 inet6_option_space.3 inet6_option_find.3
86MLINKS+=inet6_rthdr_space.3 inet6_rthdr_init.3 \
87 inet6_rthdr_space.3 inet6_rthdr_add.3 \
88 inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \
89 inet6_rthdr_space.3 inet6_rthdr_reverse.3 \
90 inet6_rthdr_space.3 inet6_rthdr_segments.3 \
91 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
92 inet6_rthdr_space.3 inet6_rthdr_getflags.3
diff --git a/src/lib/libc/net/base64.c b/src/lib/libc/net/base64.c
new file mode 100644
index 0000000000..33b6ffdc41
--- /dev/null
+++ b/src/lib/libc/net/base64.c
@@ -0,0 +1,318 @@
1/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20/*
21 * Portions Copyright (c) 1995 by International Business Machines, Inc.
22 *
23 * International Business Machines, Inc. (hereinafter called IBM) grants
24 * permission under its copyrights to use, copy, modify, and distribute this
25 * Software with or without fee, provided that the above copyright notice and
26 * all paragraphs of this notice appear in all copies, and that the name of IBM
27 * not be used in connection with the marketing of any product incorporating
28 * the Software or modifications thereof, without specific, written prior
29 * permission.
30 *
31 * To the extent it has a right to do so, IBM grants an immunity from suit
32 * under its patents, if any, for the use, sale or manufacture of products to
33 * the extent that such products are used for performing Domain Name System
34 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
35 * granted for any product per se or for any other function of any product.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
40 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
42 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/socket.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#include <arpa/nameser.h>
51
52#include <ctype.h>
53#include <resolv.h>
54#include <stdio.h>
55
56#include <stdlib.h>
57#include <string.h>
58
59/* XXX abort illegal in library */
60#define Assert(Cond) if (!(Cond)) abort()
61
62static const char Base64[] =
63 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
64static const char Pad64 = '=';
65
66/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
67 The following encoding technique is taken from RFC 1521 by Borenstein
68 and Freed. It is reproduced here in a slightly edited form for
69 convenience.
70
71 A 65-character subset of US-ASCII is used, enabling 6 bits to be
72 represented per printable character. (The extra 65th character, "=",
73 is used to signify a special processing function.)
74
75 The encoding process represents 24-bit groups of input bits as output
76 strings of 4 encoded characters. Proceeding from left to right, a
77 24-bit input group is formed by concatenating 3 8-bit input groups.
78 These 24 bits are then treated as 4 concatenated 6-bit groups, each
79 of which is translated into a single digit in the base64 alphabet.
80
81 Each 6-bit group is used as an index into an array of 64 printable
82 characters. The character referenced by the index is placed in the
83 output string.
84
85 Table 1: The Base64 Alphabet
86
87 Value Encoding Value Encoding Value Encoding Value Encoding
88 0 A 17 R 34 i 51 z
89 1 B 18 S 35 j 52 0
90 2 C 19 T 36 k 53 1
91 3 D 20 U 37 l 54 2
92 4 E 21 V 38 m 55 3
93 5 F 22 W 39 n 56 4
94 6 G 23 X 40 o 57 5
95 7 H 24 Y 41 p 58 6
96 8 I 25 Z 42 q 59 7
97 9 J 26 a 43 r 60 8
98 10 K 27 b 44 s 61 9
99 11 L 28 c 45 t 62 +
100 12 M 29 d 46 u 63 /
101 13 N 30 e 47 v
102 14 O 31 f 48 w (pad) =
103 15 P 32 g 49 x
104 16 Q 33 h 50 y
105
106 Special processing is performed if fewer than 24 bits are available
107 at the end of the data being encoded. A full encoding quantum is
108 always completed at the end of a quantity. When fewer than 24 input
109 bits are available in an input group, zero bits are added (on the
110 right) to form an integral number of 6-bit groups. Padding at the
111 end of the data is performed using the '=' character.
112
113 Since all base64 input is an integral number of octets, only the
114 -------------------------------------------------
115 following cases can arise:
116
117 (1) the final quantum of encoding input is an integral
118 multiple of 24 bits; here, the final unit of encoded
119 output will be an integral multiple of 4 characters
120 with no "=" padding,
121 (2) the final quantum of encoding input is exactly 8 bits;
122 here, the final unit of encoded output will be two
123 characters followed by two "=" padding characters, or
124 (3) the final quantum of encoding input is exactly 16 bits;
125 here, the final unit of encoded output will be three
126 characters followed by one "=" padding character.
127 */
128
129int
130b64_ntop(src, srclength, target, targsize)
131 u_char const *src;
132 size_t srclength;
133 char *target;
134 size_t targsize;
135{
136 size_t datalength = 0;
137 u_char input[3];
138 u_char output[4];
139 int i;
140
141 while (2 < srclength) {
142 input[0] = *src++;
143 input[1] = *src++;
144 input[2] = *src++;
145 srclength -= 3;
146
147 output[0] = input[0] >> 2;
148 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
149 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
150 output[3] = input[2] & 0x3f;
151 Assert(output[0] < 64);
152 Assert(output[1] < 64);
153 Assert(output[2] < 64);
154 Assert(output[3] < 64);
155
156 if (datalength + 4 > targsize)
157 return (-1);
158 target[datalength++] = Base64[output[0]];
159 target[datalength++] = Base64[output[1]];
160 target[datalength++] = Base64[output[2]];
161 target[datalength++] = Base64[output[3]];
162 }
163
164 /* Now we worry about padding. */
165 if (0 != srclength) {
166 /* Get what's left. */
167 input[0] = input[1] = input[2] = '\0';
168 for (i = 0; i < srclength; i++)
169 input[i] = *src++;
170
171 output[0] = input[0] >> 2;
172 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
173 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
174 Assert(output[0] < 64);
175 Assert(output[1] < 64);
176 Assert(output[2] < 64);
177
178 if (datalength + 4 > targsize)
179 return (-1);
180 target[datalength++] = Base64[output[0]];
181 target[datalength++] = Base64[output[1]];
182 if (srclength == 1)
183 target[datalength++] = Pad64;
184 else
185 target[datalength++] = Base64[output[2]];
186 target[datalength++] = Pad64;
187 }
188 if (datalength >= targsize)
189 return (-1);
190 target[datalength] = '\0'; /* Returned value doesn't count \0. */
191 return (datalength);
192}
193
194/* skips all whitespace anywhere.
195 converts characters, four at a time, starting at (or after)
196 src from base - 64 numbers into three 8 bit bytes in the target area.
197 it returns the number of data bytes stored at the target, or -1 on error.
198 */
199
200int
201b64_pton(src, target, targsize)
202 char const *src;
203 u_char *target;
204 size_t targsize;
205{
206 int tarindex, state, ch;
207 char *pos;
208
209 state = 0;
210 tarindex = 0;
211
212 while ((ch = *src++) != '\0') {
213 if (isspace(ch)) /* Skip whitespace anywhere. */
214 continue;
215
216 if (ch == Pad64)
217 break;
218
219 pos = strchr(Base64, ch);
220 if (pos == 0) /* A non-base64 character. */
221 return (-1);
222
223 switch (state) {
224 case 0:
225 if (target) {
226 if (tarindex >= targsize)
227 return (-1);
228 target[tarindex] = (pos - Base64) << 2;
229 }
230 state = 1;
231 break;
232 case 1:
233 if (target) {
234 if (tarindex + 1 >= targsize)
235 return (-1);
236 target[tarindex] |= (pos - Base64) >> 4;
237 target[tarindex+1] = ((pos - Base64) & 0x0f)
238 << 4 ;
239 }
240 tarindex++;
241 state = 2;
242 break;
243 case 2:
244 if (target) {
245 if (tarindex + 1 >= targsize)
246 return (-1);
247 target[tarindex] |= (pos - Base64) >> 2;
248 target[tarindex+1] = ((pos - Base64) & 0x03)
249 << 6;
250 }
251 tarindex++;
252 state = 3;
253 break;
254 case 3:
255 if (target) {
256 if (tarindex >= targsize)
257 return (-1);
258 target[tarindex] |= (pos - Base64);
259 }
260 tarindex++;
261 state = 0;
262 break;
263 }
264 }
265
266 /*
267 * We are done decoding Base-64 chars. Let's see if we ended
268 * on a byte boundary, and/or with erroneous trailing characters.
269 */
270
271 if (ch == Pad64) { /* We got a pad char. */
272 ch = *src++; /* Skip it, get next. */
273 switch (state) {
274 case 0: /* Invalid = in first position */
275 case 1: /* Invalid = in second position */
276 return (-1);
277
278 case 2: /* Valid, means one byte of info */
279 /* Skip any number of spaces. */
280 for (; ch != '\0'; ch = *src++)
281 if (!isspace(ch))
282 break;
283 /* Make sure there is another trailing = sign. */
284 if (ch != Pad64)
285 return (-1);
286 ch = *src++; /* Skip the = */
287 /* Fall through to "single trailing =" case. */
288 /* FALLTHROUGH */
289
290 case 3: /* Valid, means two bytes of info */
291 /*
292 * We know this char is an =. Is there anything but
293 * whitespace after it?
294 */
295 for (; ch != '\0'; ch = *src++)
296 if (!isspace(ch))
297 return (-1);
298
299 /*
300 * Now make sure for cases 2 and 3 that the "extra"
301 * bits that slopped past the last full byte were
302 * zeros. If we don't check them, they become a
303 * subliminal channel.
304 */
305 if (target && target[tarindex] != 0)
306 return (-1);
307 }
308 } else {
309 /*
310 * We ended by seeing the end of the string. Make sure we
311 * have no partial bytes lying around.
312 */
313 if (state != 0)
314 return (-1);
315 }
316
317 return (tarindex);
318}
diff --git a/src/lib/libc/net/byteorder.3 b/src/lib/libc/net/byteorder.3
new file mode 100644
index 0000000000..54123455c6
--- /dev/null
+++ b/src/lib/libc/net/byteorder.3
@@ -0,0 +1,206 @@
1.\" $OpenBSD: byteorder.3,v 1.13 2003/09/26 17:06:50 fgsch Exp $
2.\"
3.\" Copyright (c) 1983, 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 June 4, 1993
31.Dt BYTEORDER 3
32.Os
33.Sh NAME
34.Nm htonl ,
35.Nm htons ,
36.Nm ntohl ,
37.Nm ntohs ,
38.Nm htobe64 ,
39.Nm htobe32 ,
40.Nm htobe16 ,
41.Nm betoh64 ,
42.Nm betoh32 ,
43.Nm betoh16 ,
44.Nm htole64 ,
45.Nm htole32 ,
46.Nm htole16 ,
47.Nm letoh64 ,
48.Nm letoh32 ,
49.Nm letoh16 ,
50.Nm swap64 ,
51.Nm swap32 ,
52.Nm swap16
53.Nd convert values between different byte orderings
54.Sh SYNOPSIS
55.Fd #include <sys/types.h>
56.Ft u_int32_t
57.Fn htonl "u_int32_t host32"
58.Ft u_int16_t
59.Fn htons "u_int16_t host16"
60.Ft u_int32_t
61.Fn ntohl "u_int32_t net32"
62.Ft u_int16_t
63.Fn ntohs "u_int16_t net16"
64.Ft u_int64_t
65.Fn htobe64 "u_int64_t host64"
66.Ft u_int32_t
67.Fn htobe32 "u_int32_t host32"
68.Ft u_int16_t
69.Fn htobe16 "u_int16_t host16"
70.Ft u_int64_t
71.Fn betoh64 "u_int64_t big64"
72.Ft u_int32_t
73.Fn betoh32 "u_int32_t big32"
74.Ft u_int16_t
75.Fn betoh16 "u_int16_t big16"
76.Ft u_int64_t
77.Fn htole64 "u_int64_t host64"
78.Ft u_int32_t
79.Fn htole32 "u_int32_t host32"
80.Ft u_int16_t
81.Fn htole16 "u_int16_t host16"
82.Ft u_int64_t
83.Fn letoh64 "u_int64_t little64"
84.Ft u_int32_t
85.Fn letoh32 "u_int32_t little32"
86.Ft u_int16_t
87.Fn letoh16 "u_int16_t little16"
88.Ft u_int64_t
89.Fn swap64 "u_int32_t val64"
90.Ft u_int32_t
91.Fn swap32 "u_int32_t val32"
92.Ft u_int16_t
93.Fn swap16 "u_int16_t val16"
94.Sh DESCRIPTION
95These routines convert 16, 32 and 64-bit quantities between different
96byte orderings.
97The
98.Dq swap
99functions reverse the byte ordering of
100the given quantity, the others converts either from/to the native
101byte order used by the host to/from either little- or big-endian (a.k.a
102network) order.
103.Pp
104Apart from the swap functions, the names can be described by this form:
105{src-order}to{dst-order}{size}.
106Both {src-order} and {dst-order} can take the following forms:
107.Pp
108.Bl -tag -width "be " -offset indent -compact
109.It h
110Host order.
111.It n
112Network order (big-endian).
113.It be
114Big-endian (most significant byte first).
115.It le
116Little-endian (least significant byte first).
117.El
118.Pp
119One of the specified orderings must be
120.Sq h .
121{size} will take these forms:
122.Pp
123.Bl -tag -width "32 " -offset indent -compact
124.It l
125Long (32-bit, used in conjunction with forms involving
126.Sq n ) .
127.It s
128Short (16-bit, used in conjunction with forms involving
129.Sq n ) .
130.It 16
13116-bit.
132.It 32
13332-bit.
134.It 64
13564-bit.
136.El
137.Pp
138The swap functions are of the form: swap{size}.
139.Pp
140Names involving
141.Sq n
142convert quantities between network
143byte order and host byte order.
144The last letter
145.Pf ( Sq s
146or
147.Sq l )
148is a mnemonic
149for the traditional names for such quantities,
150.Li short
151and
152.Li long ,
153respectively.
154Today, the C concept of
155.Li short
156and
157.Li long
158integers need not coincide with this traditional misunderstanding.
159On machines which have a byte order which is the same as the network
160order, routines are defined as null macros.
161.Pp
162The functions involving either
163.Dq be ,
164.Dq le ,
165or
166.Dq swap
167use the numbers
16816, 32 and 64 for specifying the bitwidth of the quantities they operate on.
169Currently all supported architectures are either big- or little-endian
170so either the
171.Dq be
172or
173.Dq le
174variants are implemented as null macros.
175.Pp
176The routines mentioned above which have either {src-order} or {dst-order}
177set to
178.Sq n
179are most often used in
180conjunction with Internet addresses and ports as returned by
181.Xr gethostbyname 3
182and
183.Xr getservent 3 .
184.Sh SEE ALSO
185.Xr gethostbyname 3 ,
186.Xr getservent 3
187.Sh STANDARDS
188The
189.Fn htonl ,
190.Fn htons ,
191.Fn ntohl ,
192and
193.Fn ntohs
194functions conform to
195.St -p1003.1 .
196The other functions are extensions that should not be used when portability
197is required.
198.Sh HISTORY
199The
200.Nm byteorder
201functions appeared in
202.Bx 4.2 .
203.Sh BUGS
204On the vax, alpha, i386, and some mips architectures,
205bytes are handled backwards from most everyone else in the world.
206This is not expected to be fixed in the near future.
diff --git a/src/lib/libc/net/ethers.3 b/src/lib/libc/net/ethers.3
new file mode 100644
index 0000000000..72ea79bb2c
--- /dev/null
+++ b/src/lib/libc/net/ethers.3
@@ -0,0 +1,119 @@
1.\" $OpenBSD: ethers.3,v 1.15 2005/03/28 06:21:48 tedu Exp $
2.\"
3.\" Written by roland@frob.com. Public domain.
4.\"
5.Dd December 16, 1993
6.Dt ETHERS 3
7.Os
8.Sh NAME
9.Nm ether_aton ,
10.Nm ether_ntoa ,
11.Nm ether_addr ,
12.Nm ether_ntohost ,
13.Nm ether_hostton ,
14.Nm ether_line
15.Nd get ethers entry
16.Sh SYNOPSIS
17.Fd #include <netinet/if_ether.h>
18.Ft char *
19.Fn ether_ntoa "struct ether_addr *e"
20.Ft struct ether_addr *
21.Fn ether_aton "const char *s"
22.Ft int
23.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
24.Ft int
25.Fn ether_hostton "const char *hostname" "struct ether_addr *e"
26.Ft int
27.Fn ether_line "const char *l" "struct ether_addr *e" "char *hostname"
28.Sh DESCRIPTION
29Ethernet addresses are represented by the
30following structure:
31.Bd -literal -offset indent
32struct ether_addr {
33 u_int8_t ether_addr_octet[6];
34};
35.Ed
36.Pp
37The
38.Fn ether_ntoa
39function converts this structure into an
40.Tn ASCII
41string of the form
42.Dq xx:xx:xx:xx:xx:xx ,
43consisting of 6 hexadecimal numbers separated
44by colons.
45It returns a pointer to a static buffer that is reused for each call.
46The
47.Fn ether_aton
48converts an
49.Tn ASCII
50string of the same form and to a structure
51containing the 6 octets of the address.
52It returns a pointer to a static structure that is reused for each call.
53.Pp
54The
55.Fn ether_ntohost
56and
57.Fn ether_hostton
58functions interrogate the database mapping host names to Ethernet
59addresses,
60.Pa /etc/ethers .
61The
62.Fn ether_ntohost
63function looks up the given Ethernet address and writes the associated
64host name into the character buffer passed.
65This buffer should be
66.Dv MAXHOSTNAMELEN
67characters in size.
68The
69.Fn ether_hostton
70function looks up the given host name and writes the associated
71Ethernet address into the structure passed.
72Both functions return
73zero if they find the requested host name or address, and \-1 if not.
74.Pp
75Each call reads
76.Pa /etc/ethers
77from the beginning; if a
78.Ql +
79appears alone on a line in the file, then
80.Fn ether_hostton
81will consult the
82.Pa ethers.byname
83YP map, and
84.Fn ether_ntohost
85will consult the
86.Pa ethers.byaddr
87YP map.
88.Pp
89The
90.Fn ether_line
91function parses a line from the
92.Pa /etc/ethers
93file and fills in the passed
94.Li struct ether_addr
95and character buffer with the Ethernet address and host name on the line.
96It returns zero if the line was successfully parsed and \-1 if not.
97The character buffer should be
98.Dv MAXHOSTNAMELEN
99characters in size.
100.Sh FILES
101.Bl -tag -width /etc/ethers -compact
102.It Pa /etc/ethers
103.El
104.Sh SEE ALSO
105.Xr ethers 5
106.Sh HISTORY
107The
108.Fn ether_ntoa ,
109.Fn ether_aton ,
110.Fn ether_ntohost ,
111.Fn ether_hostton ,
112and
113.Fn ether_line
114functions were adopted from SunOS and appeared in
115.Nx 0.9 b.
116.Sh BUGS
117The data space used by these functions is static; if future use
118requires the data, it should be copied before any subsequent calls to
119these functions overwrite it.
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
new file mode 100644
index 0000000000..e46dcd7006
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,236 @@
1/* $OpenBSD: ethers.c,v 1.19 2005/03/28 06:19:58 tedu Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * ethers(3) a la Sun.
21 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
22 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
23 */
24
25#if defined(LIBC_SCCS) && !defined(lint)
26static char rcsid[] = "$OpenBSD: ethers.c,v 1.19 2005/03/28 06:19:58 tedu Exp $";
27#endif /* LIBC_SCCS and not lint */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/if_ether.h>
34#include <sys/param.h>
35#include <paths.h>
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41#ifdef YP
42#include <rpcsvc/ypclnt.h>
43#endif
44
45#ifndef _PATH_ETHERS
46#define _PATH_ETHERS "/etc/ethers"
47#endif
48
49static char * _ether_aton(const char *, struct ether_addr *);
50
51char *
52ether_ntoa(struct ether_addr *e)
53{
54 static char a[] = "xx:xx:xx:xx:xx:xx";
55
56 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
57 e->ether_addr_octet[0], e->ether_addr_octet[1],
58 e->ether_addr_octet[2], e->ether_addr_octet[3],
59 e->ether_addr_octet[4], e->ether_addr_octet[5]);
60
61 return (a);
62}
63
64static char *
65_ether_aton(const char *s, struct ether_addr *e)
66{
67 int i;
68 long l;
69 char *pp;
70
71 while (isspace(*s))
72 s++;
73
74 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
75 for (i = 0; i < 6; i++) {
76 l = strtol(s, &pp, 16);
77 if (pp == s || l > 0xFF || l < 0)
78 return (NULL);
79 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
80 return (NULL);
81 e->ether_addr_octet[i] = (u_char)l;
82 s = pp + 1;
83 }
84
85 /* return character after the octets ala strtol(3) */
86 return (pp);
87}
88
89struct ether_addr *
90ether_aton(const char *s)
91{
92 static struct ether_addr n;
93
94 return (_ether_aton(s, &n) ? &n : NULL);
95}
96
97int
98ether_ntohost(char *hostname, struct ether_addr *e)
99{
100 FILE *f;
101 char buf[BUFSIZ+1], *p;
102 size_t len;
103 struct ether_addr try;
104#ifdef YP
105 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
106 int trylen;
107#endif
108
109#ifdef YP
110 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
111 e->ether_addr_octet[0], e->ether_addr_octet[1],
112 e->ether_addr_octet[2], e->ether_addr_octet[3],
113 e->ether_addr_octet[4], e->ether_addr_octet[5]);
114 trylen = strlen(trybuf);
115#endif
116
117 f = fopen(_PATH_ETHERS, "r");
118 if (f == NULL)
119 return (-1);
120 while ((p = fgetln(f, &len)) != NULL) {
121 if (p[len-1] == '\n')
122 len--;
123 if (len > sizeof(buf) - 2)
124 continue;
125 (void)memcpy(buf, p, len);
126 buf[len] = '\n'; /* code assumes newlines later on */
127 buf[len+1] = '\0';
128#ifdef YP
129 /* A + in the file means try YP now. */
130 if (!strncmp(buf, "+\n", sizeof(buf))) {
131 char *ypbuf, *ypdom;
132 int ypbuflen;
133
134 if (yp_get_default_domain(&ypdom))
135 continue;
136 if (yp_match(ypdom, "ethers.byaddr", trybuf,
137 trylen, &ypbuf, &ypbuflen))
138 continue;
139 if (ether_line(ypbuf, &try, hostname) == 0) {
140 free(ypbuf);
141 (void)fclose(f);
142 return (0);
143 }
144 free(ypbuf);
145 continue;
146 }
147#endif
148 if (ether_line(buf, &try, hostname) == 0 &&
149 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
150 (void)fclose(f);
151 return (0);
152 }
153 }
154 (void)fclose(f);
155 errno = ENOENT;
156 return (-1);
157}
158
159int
160ether_hostton(const char *hostname, struct ether_addr *e)
161{
162 FILE *f;
163 char buf[BUFSIZ+1], *p;
164 char try[MAXHOSTNAMELEN];
165 size_t len;
166#ifdef YP
167 int hostlen = strlen(hostname);
168#endif
169
170 f = fopen(_PATH_ETHERS, "r");
171 if (f==NULL)
172 return (-1);
173
174 while ((p = fgetln(f, &len)) != NULL) {
175 if (p[len-1] == '\n')
176 len--;
177 if (len > sizeof(buf) - 2)
178 continue;
179 memcpy(buf, p, len);
180 buf[len] = '\n'; /* code assumes newlines later on */
181 buf[len+1] = '\0';
182#ifdef YP
183 /* A + in the file means try YP now. */
184 if (!strncmp(buf, "+\n", sizeof(buf))) {
185 char *ypbuf, *ypdom;
186 int ypbuflen;
187
188 if (yp_get_default_domain(&ypdom))
189 continue;
190 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
191 &ypbuf, &ypbuflen))
192 continue;
193 if (ether_line(ypbuf, e, try) == 0) {
194 free(ypbuf);
195 (void)fclose(f);
196 return (0);
197 }
198 free(ypbuf);
199 continue;
200 }
201#endif
202 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
203 (void)fclose(f);
204 return (0);
205 }
206 }
207 (void)fclose(f);
208 errno = ENOENT;
209 return (-1);
210}
211
212int
213ether_line(const char *line, struct ether_addr *e, char *hostname)
214{
215 char *p;
216 size_t n;
217
218 /* Parse "xx:xx:xx:xx:xx:xx" */
219 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
220 goto bad;
221
222 /* Now get the hostname */
223 while (isspace(*p))
224 p++;
225 if (*p == '\0')
226 goto bad;
227 n = strcspn(p, " \t\n");
228 if (n >= MAXHOSTNAMELEN)
229 goto bad;
230 strlcpy(hostname, p, n + 1);
231 return (0);
232
233bad:
234 errno = EINVAL;
235 return (-1);
236}
diff --git a/src/lib/libc/net/freeaddrinfo.c b/src/lib/libc/net/freeaddrinfo.c
new file mode 100644
index 0000000000..58702d0b18
--- /dev/null
+++ b/src/lib/libc/net/freeaddrinfo.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: freeaddrinfo.c,v 1.6 2005/03/25 13:24:11 otto Exp $ */
2
3/*
4 * Copyright (c) 1996, 1997, 1998, 1999, Craig Metz, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Craig Metz and
17 * by other contributors.
18 * 4. Neither the name of the author nor the names of 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 <stdlib.h>
36#include <netdb.h>
37
38void
39freeaddrinfo(struct addrinfo *ai)
40{
41 struct addrinfo *p;
42
43 do {
44 p = ai;
45 ai = ai->ai_next;
46 if (p->ai_canonname)
47 free(p->ai_canonname);
48 free((void *)p);
49 } while (ai);
50}
diff --git a/src/lib/libc/net/gai_strerror.3 b/src/lib/libc/net/gai_strerror.3
new file mode 100644
index 0000000000..d0a636ee03
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.3
@@ -0,0 +1,93 @@
1.\" $OpenBSD: gai_strerror.3,v 1.5 2005/01/06 03:50:46 itojun Exp $
2.\" $KAME: gai_strerror.3,v 1.1 2005/01/05 03:04:47 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
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 ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GAI_STRERROR 3
21.Os
22.Sh NAME
23.Nm gai_strerror
24.Nd get error message string from EAI_xxx error code
25.Sh SYNOPSIS
26.Fd #include <sys/types.h>
27.Fd #include <sys/socket.h>
28.Fd #include <netdb.h>
29.Ft "const char *"
30.Fn gai_strerror "int ecode"
31.Sh DESCRIPTION
32The
33.Fn gai_strerror
34function returns an error message string corresponding to the error code
35returned by
36.Xr getaddrinfo 3
37or
38.Xr getnameinfo 3 .
39.Pp
40The following error codes and their meaning are defined in
41.Aq Pa netdb.h :
42.Pp
43.Bl -tag -width "EAI_ADDRFAMILYXX" -offset indent -compact
44.It Dv EAI_ADDRFAMILY
45address family for
46.Fa hostname
47not supported
48.It Dv EAI_AGAIN
49temporary failure in name resolution
50.It Dv EAI_BADFLAGS
51invalid value for
52.Fa ai_flags
53.It Dv EAI_BADHINTS
54invalid value for
55.Fa hints
56.It Dv EAI_FAIL
57non-recoverable failure in name resolution
58.It Dv EAI_FAMILY
59.Fa ai_family
60not supported.
61.It Dv EAI_MEMORY
62memory allocation failure
63.It Dv EAI_NODATA
64no address associated with
65.Fa hostname
66.It Dv EAI_NONAME
67.Fa hostname
68or
69.Fa servname
70not provided, or not known
71.It Dv EAI_PROTOCOL
72resolved protocol is unknown
73.It Dv EAI_SERVICE
74.Fa servname
75not supported for
76.Fa ai_socktype
77.It Dv EAI_SOCKTYPE
78.Fa ai_socktype
79not supported
80.It Dv EAI_SYSTEM
81system error returned in
82.Va errno
83.El
84.Sh RETURN VALUES
85.Fn gai_strerror
86returns a pointer to the error message string corresponding to
87.Fa ecode .
88If
89.Fa ecode
90is out of range, an implementation-specific error message string is returned.
91.Sh SEE ALSO
92.Xr getaddrinfo 3 ,
93.Xr getnameinfo 3
diff --git a/src/lib/libc/net/gai_strerror.c b/src/lib/libc/net/gai_strerror.c
new file mode 100644
index 0000000000..767bc2f7e8
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.c
@@ -0,0 +1,76 @@
1/* $OpenBSD: gai_strerror.c,v 1.6 2004/12/20 22:35:32 millert Exp $ */
2
3/*
4 * Copyright (c) 1997-1999, Craig Metz, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Craig Metz and
17 * by other contributors.
18 * 4. Neither the name of the author nor the names of 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/* gai_strerror() v1.38 */
36
37#include <sys/types.h>
38#include <netdb.h>
39#include <errno.h>
40
41const char *
42gai_strerror(int errnum)
43{
44 switch (errnum) {
45 case 0:
46 return "no error";
47 case EAI_BADFLAGS:
48 return "invalid value for ai_flags";
49 case EAI_NONAME:
50 return "name or service is not known";
51 case EAI_AGAIN:
52 return "temporary failure in name resolution";
53 case EAI_FAIL:
54 return "non-recoverable failure in name resolution";
55 case EAI_NODATA:
56 return "no address associated with name";
57 case EAI_FAMILY:
58 return "ai_family not supported";
59 case EAI_SOCKTYPE:
60 return "ai_socktype not supported";
61 case EAI_SERVICE:
62 return "service not supported for ai_socktype";
63 case EAI_ADDRFAMILY:
64 return "address family for name not supported";
65 case EAI_MEMORY:
66 return "memory allocation failure";
67 case EAI_SYSTEM:
68 return "system error";
69 case EAI_BADHINTS:
70 return "invalid value for hints";
71 case EAI_PROTOCOL:
72 return "resolved protocol is unknown";
73 default:
74 return "unknown/invalid error";
75 }
76}
diff --git a/src/lib/libc/net/getaddrinfo.3 b/src/lib/libc/net/getaddrinfo.3
new file mode 100644
index 0000000000..b82dda5937
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,439 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.40 2005/03/12 00:02:07 claudio Exp $
2.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
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 ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GETADDRINFO 3
21.Os
22.Sh NAME
23.Nm getaddrinfo ,
24.Nm freeaddrinfo
25.Nd host and service name to socket address structure
26.Sh SYNOPSIS
27.Fd #include <sys/types.h>
28.Fd #include <sys/socket.h>
29.Fd #include <netdb.h>
30.Ft int
31.Fn getaddrinfo "const char *hostname" "const char *servname" \
32 "const struct addrinfo *hints" "struct addrinfo **res"
33.Ft void
34.Fn freeaddrinfo "struct addrinfo *ai"
35.Sh DESCRIPTION
36The
37.Fn getaddrinfo
38function is used to get a list of
39.Tn IP
40addresses and port numbers for host
41.Fa hostname
42and service
43.Fa servname .
44It is a replacement for and provides more flexibility than the
45.Xr gethostbyname 3
46and
47.Xr getservbyname 3
48functions.
49.Pp
50The
51.Fa hostname
52and
53.Fa servname
54arguments are either pointers to NUL-terminated strings or the null pointer.
55An acceptable value for
56.Fa hostname
57is either a valid host name or a numeric host address string consisting
58of a dotted decimal IPv4 address or an IPv6 address.
59The
60.Fa servname
61is either a decimal port number or a service name listed in
62.Xr services 5 .
63At least one of
64.Fa hostname
65and
66.Fa servname
67must be non-null.
68.Pp
69.Fa hints
70is an optional pointer to a
71.Li struct addrinfo ,
72as defined by
73.Aq Pa netdb.h :
74.Bd -literal
75struct addrinfo {
76 int ai_flags; /* input flags */
77 int ai_family; /* protocol family for socket */
78 int ai_socktype; /* socket type */
79 int ai_protocol; /* protocol for socket */
80 socklen_t ai_addrlen; /* length of socket-address */
81 struct sockaddr *ai_addr; /* socket-address for socket */
82 char *ai_canonname; /* canonical name for service location */
83 struct addrinfo *ai_next; /* pointer to next in list */
84};
85.Ed
86.Pp
87This structure can be used to provide hints concerning the type of socket
88that the caller supports or wishes to use.
89The caller can supply the following structure elements in
90.Fa hints :
91.Bl -tag -width "ai_socktypeXX"
92.It Fa ai_family
93The protocol family that should be used.
94When
95.Fa ai_family
96is set to
97.Dv PF_UNSPEC ,
98it means the caller will accept any protocol family supported by the
99operating system.
100.It Fa ai_socktype
101Denotes the type of socket that is wanted:
102.Dv SOCK_STREAM ,
103.Dv SOCK_DGRAM ,
104or
105.Dv SOCK_RAW .
106When
107.Fa ai_socktype
108is zero the caller will accept any socket type.
109.It Fa ai_protocol
110Indicates which transport protocol is desired,
111.Dv IPPROTO_UDP
112or
113.Dv IPPROTO_TCP .
114If
115.Fa ai_protocol
116is zero the caller will accept any protocol.
117.It Fa ai_flags
118.Fa ai_flags
119is formed by
120.Tn OR Ns 'ing
121the following values:
122.Bl -tag -width "AI_CANONNAMEXX"
123.It Dv AI_CANONNAME
124If the
125.Dv AI_CANONNAME
126bit is set, a successful call to
127.Fn getaddrinfo
128will return a NUL-terminated string containing the canonical name
129of the specified hostname in the
130.Fa ai_canonname
131element of the first
132.Li addrinfo
133structure returned.
134.It Dv AI_NUMERICHOST
135If the
136.Dv AI_NUMERICHOST
137bit is set, it indicates that
138.Fa hostname
139should be treated as a numeric string defining an IPv4 or IPv6 address
140and no name resolution should be attempted.
141.It Dv AI_PASSIVE
142If the
143.Dv AI_PASSIVE
144bit is set it indicates that the returned socket address structure
145is intended for use in a call to
146.Xr bind 2 .
147In this case, if the
148.Fa hostname
149argument is the null pointer, then the IP address portion of the
150socket address structure will be set to
151.Dv INADDR_ANY
152for an IPv4 address or
153.Dv IN6ADDR_ANY_INIT
154for an IPv6 address.
155.Pp
156If the
157.Dv AI_PASSIVE
158bit is not set, the returned socket address structure will be ready
159for use in a call to
160.Xr connect 2
161for a connection-oriented protocol or
162.Xr connect 2 ,
163.Xr sendto 2 ,
164or
165.Xr sendmsg 2
166if a connectionless protocol was chosen.
167The
168.Tn IP
169address portion of the socket address structure will be set to the
170loopback address if
171.Fa hostname
172is the null pointer and
173.Dv AI_PASSIVE
174is not set.
175.El
176.El
177.Pp
178All other elements of the
179.Li addrinfo
180structure passed via
181.Fa hints
182must be zero or the null pointer.
183.Pp
184If
185.Fa hints
186is the null pointer,
187.Fn getaddrinfo
188behaves as if the caller provided a
189.Li struct addrinfo
190with
191.Fa ai_family
192set to
193.Dv PF_UNSPEC
194and all other elements set to zero or
195.Dv NULL .
196.Pp
197After a successful call to
198.Fn getaddrinfo ,
199.Fa *res
200is a pointer to a linked list of one or more
201.Li addrinfo
202structures.
203The list can be traversed by following the
204.Fa ai_next
205pointer in each
206.Li addrinfo
207structure until a null pointer is encountered.
208The three members
209.Fa ai_family ,
210.Fa ai_socktype ,
211and
212.Fa ai_protocol
213in each returned
214.Li addrinfo
215structure are suitable for a call to
216.Xr socket 2 .
217For each
218.Li addrinfo
219structure in the list, the
220.Fa ai_addr
221member points to a filled-in socket address structure of length
222.Fa ai_addrlen .
223.Pp
224This implementation of
225.Fn getaddrinfo
226allows numeric IPv6 address notation with scope identifier,
227as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
228By appending the percent character and scope identifier to addresses,
229one can fill the
230.Li sin6_scope_id
231field for addresses.
232This would make management of scoped addresses easier
233and allows cut-and-paste input of scoped addresses.
234.Pp
235At this moment the code supports only link-local addresses with the format.
236The scope identifier is hardcoded to the name of the hardware interface
237associated
238with the link
239.Po
240such as
241.Li ne0
242.Pc .
243An example is
244.Dq Li fe80::1%ne0 ,
245which means
246.Do
247.Li fe80::1
248on the link associated with the
249.Li ne0
250interface
251.Dc .
252.Pp
253The current implementation assumes a one-to-one relationship between
254the interface and link, which is not necessarily true from the specification.
255.Pp
256All of the information returned by
257.Fn getaddrinfo
258is dynamically allocated: the
259.Li addrinfo
260structures themselves as well as the socket address structures and
261the canonical host name strings included in the
262.Li addrinfo
263structures.
264.Pp
265Memory allocated for the dynamically allocated structures created by
266a successful call to
267.Fn getaddrinfo
268is released by the
269.Fn freeaddrinfo
270function.
271The
272.Fa ai
273pointer should be a
274.Li addrinfo
275structure created by a call to
276.Fn getaddrinfo .
277.Sh RETURN VALUES
278.Fn getaddrinfo
279returns zero on success or one of the error codes listed in
280.Xr gai_strerror 3
281if an error occurs.
282If an error occurs, no memory is allocated by
283.Fn getaddrinfo ,
284therefore it is not necessary to release the
285.Li addrinfo
286structure(s).
287.Sh EXAMPLES
288The following code tries to connect to
289.Dq Li www.kame.net
290service
291.Dq Li http
292via a stream socket.
293It loops through all the addresses available, regardless of address family.
294If the destination resolves to an IPv4 address, it will use an
295.Dv AF_INET
296socket.
297Similarly, if it resolves to IPv6, an
298.Dv AF_INET6
299socket is used.
300Observe that there is no hardcoded reference to a particular address family.
301The code works even if
302.Fn getaddrinfo
303returns addresses that are not IPv4/v6.
304.Bd -literal -offset indent
305struct addrinfo hints, *res, *res0;
306int error;
307int s;
308const char *cause = NULL;
309
310memset(&hints, 0, sizeof(hints));
311hints.ai_family = PF_UNSPEC;
312hints.ai_socktype = SOCK_STREAM;
313error = getaddrinfo("www.kame.net", "http", &hints, &res0);
314if (error) {
315 errx(1, "%s", gai_strerror(error));
316 /*NOTREACHED*/
317}
318s = -1;
319for (res = res0; res; res = res->ai_next) {
320 s = socket(res->ai_family, res->ai_socktype,
321 res->ai_protocol);
322 if (s < 0) {
323 cause = "socket";
324 continue;
325 }
326
327 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
328 cause = "connect";
329 close(s);
330 s = -1;
331 continue;
332 }
333
334 break; /* okay we got one */
335}
336if (s < 0) {
337 err(1, "%s", cause);
338 /*NOTREACHED*/
339}
340freeaddrinfo(res0);
341.Ed
342.Pp
343The following example tries to open a wildcard listening socket onto service
344.Dq Li http ,
345for all the address families available.
346.Bd -literal -offset indent
347struct addrinfo hints, *res, *res0;
348int error;
349int s[MAXSOCK];
350int nsock;
351const char *cause = NULL;
352
353memset(&hints, 0, sizeof(hints));
354hints.ai_family = PF_UNSPEC;
355hints.ai_socktype = SOCK_STREAM;
356hints.ai_flags = AI_PASSIVE;
357error = getaddrinfo(NULL, "http", &hints, &res0);
358if (error) {
359 errx(1, "%s", gai_strerror(error));
360 /*NOTREACHED*/
361}
362nsock = 0;
363for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
364 s[nsock] = socket(res->ai_family, res->ai_socktype,
365 res->ai_protocol);
366 if (s[nsock] < 0) {
367 cause = "socket";
368 continue;
369 }
370
371 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
372 cause = "bind";
373 close(s[nsock]);
374 continue;
375 }
376 (void) listen(s[nsock], 5);
377
378 nsock++;
379}
380if (nsock == 0) {
381 err(1, "%s", cause);
382 /*NOTREACHED*/
383}
384freeaddrinfo(res0);
385.Ed
386.Sh SEE ALSO
387.Xr bind 2 ,
388.Xr connect 2 ,
389.Xr send 2 ,
390.Xr socket 2 ,
391.Xr gai_strerror 3 ,
392.Xr gethostbyname 3 ,
393.Xr getnameinfo 3 ,
394.Xr getservbyname 3 ,
395.Xr resolver 3 ,
396.Xr hosts 5 ,
397.Xr resolv.conf 5 ,
398.Xr services 5 ,
399.Xr hostname 7 ,
400.Xr named 8
401.Rs
402.%A R. Gilligan
403.%A S. Thomson
404.%A J. Bound
405.%A J. McCann
406.%A W. Stevens
407.%T Basic Socket Interface Extensions for IPv6
408.%R RFC 3493
409.%D February 2003
410.Re
411.Rs
412.%A S. Deering
413.%A B. Haberman
414.%A T. Jinmei
415.%A E. Nordmark
416.%A B. Zill
417.%T "IPv6 Scoped Address Architecture"
418.%R internet draft
419.%N draft-ietf-ipv6-scoping-arch-02.txt
420.%O work in progress material
421.Re
422.Rs
423.%A Craig Metz
424.%T Protocol Independence Using the Sockets API
425.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
426.%D June 2000
427.Re
428.Sh STANDARDS
429The
430.Fn getaddrinfo
431function is defined by the
432.St -p1003.1g-2000
433draft specification and documented in
434.Dv "RFC 3493" ,
435.Dq Basic Socket Interface Extensions for IPv6 .
436.Sh BUGS
437The implementation of
438.Fn getaddrinfo
439is not thread-safe.
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000000..19967e8432
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1804 @@
1/* $OpenBSD: getaddrinfo.c,v 1.52 2005/03/30 02:58:28 tedu Exp $ */
2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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. Neither the name of the project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked.
36 * - Return values. There are nonstandard return values defined and used
37 * in the source code. This is because RFC2553 is silent about which error
38 * code must be returned for which situation.
39 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
40 * says to use inet_aton() to convert IPv4 numeric to binary (alows
41 * classful form as a result).
42 * current code - disallow classful form for IPv4 (due to use of inet_pton).
43 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
44 * invalid.
45 * current code - SEGV on freeaddrinfo(NULL)
46 * Note:
47 * - We use getipnodebyname() just for thread-safeness. There's no intent
48 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 * getipnodebyname().
50 * - The code filters out AFs that are not supported by the kernel,
51 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
52 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 * in ai_flags?
54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
55 * (1) what should we do against numeric hostname (2) what should we do
56 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
57 * non-loopback address configured? global address configured?
58 * - To avoid search order issue, we have a big amount of code duplicate
59 * from gethnamaddr.c and some other places. The issues that there's no
60 * lower layer function to lookup "IPv4 or IPv6" record. Calling
61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
62 * follows:
63 * - The code makes use of following calls when asked to resolver with
64 * ai_family = PF_UNSPEC:
65 * getipnodebyname(host, AF_INET6);
66 * getipnodebyname(host, AF_INET);
67 * This will result in the following queries if the node is configure to
68 * prefer /etc/hosts than DNS:
69 * lookup /etc/hosts for IPv6 address
70 * lookup DNS for IPv6 address
71 * lookup /etc/hosts for IPv4 address
72 * lookup DNS for IPv4 address
73 * which may not meet people's requirement.
74 * The right thing to happen is to have underlying layer which does
75 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
76 * This would result in a bit of code duplicate with _dns_ghbyname() and
77 * friends.
78 */
79
80#ifndef INET6
81#define INET6
82#endif
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <net/if.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91#include <netdb.h>
92#include <resolv.h>
93#include <string.h>
94#include <stdlib.h>
95#include <stddef.h>
96#include <ctype.h>
97#include <unistd.h>
98#include <stdio.h>
99#include <errno.h>
100
101#include <syslog.h>
102#include <stdarg.h>
103
104#ifdef YP
105#include <rpc/rpc.h>
106#include <rpcsvc/yp.h>
107#include <rpcsvc/ypclnt.h>
108#include "ypinternal.h"
109#endif
110
111#include "thread_private.h"
112
113#define SUCCESS 0
114#define ANY 0
115#define YES 1
116#define NO 0
117
118static const char in_addrany[] = { 0, 0, 0, 0 };
119static const char in6_addrany[] = {
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
121};
122static const char in_loopback[] = { 127, 0, 0, 1 };
123static const char in6_loopback[] = {
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
125};
126
127static const struct afd {
128 int a_af;
129 int a_addrlen;
130 int a_socklen;
131 int a_off;
132 const char *a_addrany;
133 const char *a_loopback;
134 int a_scoped;
135} afdl [] = {
136#ifdef INET6
137 {PF_INET6, sizeof(struct in6_addr),
138 sizeof(struct sockaddr_in6),
139 offsetof(struct sockaddr_in6, sin6_addr),
140 in6_addrany, in6_loopback, 1},
141#endif
142 {PF_INET, sizeof(struct in_addr),
143 sizeof(struct sockaddr_in),
144 offsetof(struct sockaddr_in, sin_addr),
145 in_addrany, in_loopback, 0},
146 {0, 0, 0, 0, NULL, NULL, 0},
147};
148
149struct explore {
150 int e_af;
151 int e_socktype;
152 int e_protocol;
153 const char *e_protostr;
154 int e_wild;
155#define WILD_AF(ex) ((ex)->e_wild & 0x01)
156#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
157#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
158};
159
160static const struct explore explore[] = {
161#if 0
162 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
163#endif
164#ifdef INET6
165 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
166 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
167 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
168#endif
169 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
170 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
171 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
172 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
173 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
174 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
175 { -1, 0, 0, NULL, 0 },
176};
177
178#ifdef INET6
179#define PTON_MAX 16
180#else
181#define PTON_MAX 4
182#endif
183
184#define MAXPACKET (64*1024)
185
186typedef union {
187 HEADER hdr;
188 u_char buf[MAXPACKET];
189} querybuf;
190
191struct res_target {
192 struct res_target *next;
193 const char *name; /* domain name */
194 int qclass, qtype; /* class and type of query */
195 u_char *answer; /* buffer to put answer */
196 int anslen; /* size of answer buffer */
197 int n; /* result length */
198};
199
200static int str2number(const char *);
201static int explore_fqdn(const struct addrinfo *, const char *,
202 const char *, struct addrinfo **);
203static int explore_null(const struct addrinfo *,
204 const char *, struct addrinfo **);
205static int explore_numeric(const struct addrinfo *, const char *,
206 const char *, struct addrinfo **, const char *);
207static int explore_numeric_scope(const struct addrinfo *, const char *,
208 const char *, struct addrinfo **);
209static int get_canonname(const struct addrinfo *,
210 struct addrinfo *, const char *);
211static struct addrinfo *get_ai(const struct addrinfo *,
212 const struct afd *, const char *);
213static int get_portmatch(const struct addrinfo *, const char *);
214static int get_port(struct addrinfo *, const char *, int);
215static const struct afd *find_afd(int);
216#ifdef INET6
217static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
218#endif
219
220static void _sethtent(void);
221static void _endhtent(void);
222static struct addrinfo * _gethtent(const char *, const struct addrinfo *);
223static struct addrinfo *_files_getaddrinfo(const char *,
224 const struct addrinfo *);
225
226#ifdef YP
227static struct addrinfo *_yphostent(char *, const struct addrinfo *);
228static struct addrinfo *_yp_getaddrinfo(const char *,
229 const struct addrinfo *);
230#endif
231
232static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
233 const struct addrinfo *);
234static int res_queryN(const char *, struct res_target *);
235static int res_searchN(const char *, struct res_target *);
236static int res_querydomainN(const char *, const char *, struct res_target *);
237static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *);
238
239
240/* XXX macros that make external reference is BAD. */
241
242#define GET_AI(ai, afd, addr) \
243do { \
244 /* external reference: pai, error, and label free */ \
245 (ai) = get_ai(pai, (afd), (addr)); \
246 if ((ai) == NULL) { \
247 error = EAI_MEMORY; \
248 goto free; \
249 } \
250} while (/*CONSTCOND*/0)
251
252#define GET_PORT(ai, serv) \
253do { \
254 /* external reference: error and label free */ \
255 error = get_port((ai), (serv), 0); \
256 if (error != 0) \
257 goto free; \
258} while (/*CONSTCOND*/0)
259
260#define GET_CANONNAME(ai, str) \
261do { \
262 /* external reference: pai, error and label free */ \
263 error = get_canonname(pai, (ai), (str)); \
264 if (error != 0) \
265 goto free; \
266} while (/*CONSTCOND*/0)
267
268#define ERR(err) \
269do { \
270 /* external reference: error, and label bad */ \
271 error = (err); \
272 goto bad; \
273 /*NOTREACHED*/ \
274} while (/*CONSTCOND*/0)
275
276#define MATCH_FAMILY(x, y, w) \
277 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
278#define MATCH(x, y, w) \
279 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
280
281static int
282str2number(const char *p)
283{
284 char *ep;
285 unsigned long v;
286
287 if (*p == '\0')
288 return -1;
289 ep = NULL;
290 errno = 0;
291 v = strtoul(p, &ep, 10);
292 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
293 return v;
294 else
295 return -1;
296}
297
298int
299getaddrinfo(const char *hostname, const char *servname,
300 const struct addrinfo *hints, struct addrinfo **res)
301{
302 struct addrinfo sentinel;
303 struct addrinfo *cur;
304 int error = 0;
305 struct addrinfo ai;
306 struct addrinfo ai0;
307 struct addrinfo *pai;
308 const struct explore *ex;
309
310 memset(&sentinel, 0, sizeof(sentinel));
311 cur = &sentinel;
312 pai = &ai;
313 pai->ai_flags = 0;
314 pai->ai_family = PF_UNSPEC;
315 pai->ai_socktype = ANY;
316 pai->ai_protocol = ANY;
317 pai->ai_addrlen = 0;
318 pai->ai_canonname = NULL;
319 pai->ai_addr = NULL;
320 pai->ai_next = NULL;
321
322 if (hostname == NULL && servname == NULL)
323 return EAI_NONAME;
324 if (hints) {
325 /* error check for hints */
326 if (hints->ai_addrlen || hints->ai_canonname ||
327 hints->ai_addr || hints->ai_next)
328 ERR(EAI_BADHINTS); /* xxx */
329 if (hints->ai_flags & ~AI_MASK)
330 ERR(EAI_BADFLAGS);
331 switch (hints->ai_family) {
332 case PF_UNSPEC:
333 case PF_INET:
334#ifdef INET6
335 case PF_INET6:
336#endif
337 break;
338 default:
339 ERR(EAI_FAMILY);
340 }
341 memcpy(pai, hints, sizeof(*pai));
342
343 /*
344 * if both socktype/protocol are specified, check if they
345 * are meaningful combination.
346 */
347 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
348 for (ex = explore; ex->e_af >= 0; ex++) {
349 if (pai->ai_family != ex->e_af)
350 continue;
351 if (ex->e_socktype == ANY)
352 continue;
353 if (ex->e_protocol == ANY)
354 continue;
355 if (pai->ai_socktype == ex->e_socktype
356 && pai->ai_protocol != ex->e_protocol) {
357 ERR(EAI_BADHINTS);
358 }
359 }
360 }
361 }
362
363 /*
364 * check for special cases. (1) numeric servname is disallowed if
365 * socktype/protocol are left unspecified. (2) servname is disallowed
366 * for raw and other inet{,6} sockets.
367 */
368 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
369#ifdef PF_INET6
370 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
371#endif
372 ) {
373 ai0 = *pai; /* backup *pai */
374
375 if (pai->ai_family == PF_UNSPEC) {
376#ifdef PF_INET6
377 pai->ai_family = PF_INET6;
378#else
379 pai->ai_family = PF_INET;
380#endif
381 }
382 error = get_portmatch(pai, servname);
383 if (error)
384 ERR(error);
385
386 *pai = ai0;
387 }
388
389 ai0 = *pai;
390
391 /* NULL hostname, or numeric hostname */
392 for (ex = explore; ex->e_af >= 0; ex++) {
393 *pai = ai0;
394
395 /* PF_UNSPEC entries are prepared for DNS queries only */
396 if (ex->e_af == PF_UNSPEC)
397 continue;
398
399 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
400 continue;
401 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
402 continue;
403 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
404 continue;
405
406 if (pai->ai_family == PF_UNSPEC)
407 pai->ai_family = ex->e_af;
408 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
409 pai->ai_socktype = ex->e_socktype;
410 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
411 pai->ai_protocol = ex->e_protocol;
412
413 if (hostname == NULL)
414 error = explore_null(pai, servname, &cur->ai_next);
415 else
416 error = explore_numeric_scope(pai, hostname, servname,
417 &cur->ai_next);
418
419 if (error)
420 goto free;
421
422 while (cur && cur->ai_next)
423 cur = cur->ai_next;
424 }
425
426 /*
427 * XXX
428 * If numreic representation of AF1 can be interpreted as FQDN
429 * representation of AF2, we need to think again about the code below.
430 */
431 if (sentinel.ai_next)
432 goto good;
433
434 if (hostname == NULL)
435 ERR(EAI_NODATA);
436 if (pai->ai_flags & AI_NUMERICHOST)
437 ERR(EAI_NONAME);
438
439 /*
440 * hostname as alphabetical name.
441 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
442 * outer loop by AFs.
443 */
444 for (ex = explore; ex->e_af >= 0; ex++) {
445 *pai = ai0;
446
447 /* require exact match for family field */
448 if (pai->ai_family != ex->e_af)
449 continue;
450
451 if (!MATCH(pai->ai_socktype, ex->e_socktype,
452 WILD_SOCKTYPE(ex))) {
453 continue;
454 }
455 if (!MATCH(pai->ai_protocol, ex->e_protocol,
456 WILD_PROTOCOL(ex))) {
457 continue;
458 }
459
460 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
461 pai->ai_socktype = ex->e_socktype;
462 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
463 pai->ai_protocol = ex->e_protocol;
464
465 error = explore_fqdn(pai, hostname, servname,
466 &cur->ai_next);
467
468 while (cur && cur->ai_next)
469 cur = cur->ai_next;
470 }
471
472 /* XXX */
473 if (sentinel.ai_next)
474 error = 0;
475
476 if (error)
477 goto free;
478 if (error == 0) {
479 if (sentinel.ai_next) {
480 good:
481 *res = sentinel.ai_next;
482 return SUCCESS;
483 } else
484 error = EAI_FAIL;
485 }
486 free:
487 bad:
488 if (sentinel.ai_next)
489 freeaddrinfo(sentinel.ai_next);
490 *res = NULL;
491 return error;
492}
493
494/*
495 * FQDN hostname, DNS lookup
496 */
497
498static int
499explore_fqdn(const struct addrinfo *pai, const char *hostname,
500 const char *servname, struct addrinfo **res)
501{
502 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
503 struct addrinfo *result;
504 struct addrinfo *cur;
505 int error = 0;
506 char lookups[MAXDNSLUS];
507 int i;
508 _THREAD_PRIVATE_MUTEX(_explore_mutex);
509
510 result = NULL;
511
512 /*
513 * if the servname does not match socktype/protocol, ignore it.
514 */
515 if (get_portmatch(pai, servname) != 0) {
516 return 0;
517 }
518
519 if (_res_init(0) == -1)
520 strlcpy(lookups, "f", sizeof lookups);
521 else {
522 bcopy(_resp->lookups, lookups, sizeof lookups);
523 if (lookups[0] == '\0')
524 strlcpy(lookups, "bf", sizeof lookups);
525 }
526
527 /*
528 * The yp/dns/files getaddrinfo functions are not thread safe.
529 * Protect them with a mutex.
530 */
531 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
532 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
533 switch (lookups[i]) {
534#ifdef YP
535 case 'y':
536 result = _yp_getaddrinfo(hostname, pai);
537 break;
538#endif
539 case 'b':
540 result = _dns_getaddrinfo(hostname, pai);
541 break;
542 case 'f':
543 result = _files_getaddrinfo(hostname, pai);
544 break;
545 }
546 }
547 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
548 if (result) {
549 for (cur = result; cur; cur = cur->ai_next) {
550 GET_PORT(cur, servname);
551 /* canonname should be filled already */
552 }
553 *res = result;
554 return 0;
555 } else {
556 /* translate error code */
557 switch (h_errno) {
558 case NETDB_SUCCESS:
559 error = EAI_FAIL; /*XXX strange */
560 break;
561 case HOST_NOT_FOUND:
562 error = EAI_NODATA;
563 break;
564 case TRY_AGAIN:
565 error = EAI_AGAIN;
566 break;
567 case NO_RECOVERY:
568 error = EAI_FAIL;
569 break;
570 case NO_DATA:
571#if NO_ADDRESS != NO_DATA
572 case NO_ADDRESS:
573#endif
574 error = EAI_NODATA;
575 break;
576 default: /* unknown ones */
577 error = EAI_FAIL;
578 break;
579 }
580 }
581
582free:
583 if (result)
584 freeaddrinfo(result);
585 return error;
586}
587
588/*
589 * hostname == NULL.
590 * passive socket -> anyaddr (0.0.0.0 or ::)
591 * non-passive socket -> localhost (127.0.0.1 or ::1)
592 */
593static int
594explore_null(const struct addrinfo *pai, const char *servname,
595 struct addrinfo **res)
596{
597 int s;
598 const struct afd *afd;
599 struct addrinfo *cur;
600 struct addrinfo sentinel;
601 int error;
602
603 *res = NULL;
604 sentinel.ai_next = NULL;
605 cur = &sentinel;
606
607 /*
608 * filter out AFs that are not supported by the kernel
609 * XXX errno?
610 */
611 s = socket(pai->ai_family, SOCK_DGRAM, 0);
612 if (s < 0) {
613 if (errno != EMFILE)
614 return 0;
615 } else
616 close(s);
617
618 /*
619 * if the servname does not match socktype/protocol, ignore it.
620 */
621 if (get_portmatch(pai, servname) != 0)
622 return 0;
623
624 afd = find_afd(pai->ai_family);
625 if (afd == NULL)
626 return 0;
627
628 if (pai->ai_flags & AI_PASSIVE) {
629 GET_AI(cur->ai_next, afd, afd->a_addrany);
630 /* xxx meaningless?
631 * GET_CANONNAME(cur->ai_next, "anyaddr");
632 */
633 GET_PORT(cur->ai_next, servname);
634 } else {
635 GET_AI(cur->ai_next, afd, afd->a_loopback);
636 /* xxx meaningless?
637 * GET_CANONNAME(cur->ai_next, "localhost");
638 */
639 GET_PORT(cur->ai_next, servname);
640 }
641 cur = cur->ai_next;
642
643 *res = sentinel.ai_next;
644 return 0;
645
646free:
647 if (sentinel.ai_next)
648 freeaddrinfo(sentinel.ai_next);
649 return error;
650}
651
652/*
653 * numeric hostname
654 */
655static int
656explore_numeric(const struct addrinfo *pai, const char *hostname,
657 const char *servname, struct addrinfo **res, const char *canonname)
658{
659 const struct afd *afd;
660 struct addrinfo *cur;
661 struct addrinfo sentinel;
662 int error;
663 char pton[PTON_MAX];
664
665 *res = NULL;
666 sentinel.ai_next = NULL;
667 cur = &sentinel;
668
669 /*
670 * if the servname does not match socktype/protocol, ignore it.
671 */
672 if (get_portmatch(pai, servname) != 0)
673 return 0;
674
675 afd = find_afd(pai->ai_family);
676 if (afd == NULL)
677 return 0;
678
679 switch (afd->a_af) {
680#if 0 /*X/Open spec*/
681 case AF_INET:
682 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
683 if (pai->ai_family == afd->a_af ||
684 pai->ai_family == PF_UNSPEC /*?*/) {
685 GET_AI(cur->ai_next, afd, pton);
686 GET_PORT(cur->ai_next, servname);
687 if ((pai->ai_flags & AI_CANONNAME)) {
688 /*
689 * Set the numeric address itself as
690 * the canonical name, based on a
691 * clarification in rfc2553bis-03.
692 */
693 GET_CANONNAME(cur->ai_next, canonname);
694 }
695 while (cur && cur->ai_next)
696 cur = cur->ai_next;
697 } else
698 ERR(EAI_FAMILY); /*xxx*/
699 }
700 break;
701#endif
702 default:
703 if (inet_pton(afd->a_af, hostname, pton) == 1) {
704 if (pai->ai_family == afd->a_af ||
705 pai->ai_family == PF_UNSPEC /*?*/) {
706 GET_AI(cur->ai_next, afd, pton);
707 GET_PORT(cur->ai_next, servname);
708 if ((pai->ai_flags & AI_CANONNAME)) {
709 /*
710 * Set the numeric address itself as
711 * the canonical name, based on a
712 * clarification in rfc2553bis-03.
713 */
714 GET_CANONNAME(cur->ai_next, canonname);
715 }
716 while (cur && cur->ai_next)
717 cur = cur->ai_next;
718 } else
719 ERR(EAI_FAMILY); /*xxx*/
720 }
721 break;
722 }
723
724 *res = sentinel.ai_next;
725 return 0;
726
727free:
728bad:
729 if (sentinel.ai_next)
730 freeaddrinfo(sentinel.ai_next);
731 return error;
732}
733
734/*
735 * numeric hostname with scope
736 */
737static int
738explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
739 const char *servname, struct addrinfo **res)
740{
741#if !defined(SCOPE_DELIMITER) || !defined(INET6)
742 return explore_numeric(pai, hostname, servname, res, hostname);
743#else
744 const struct afd *afd;
745 struct addrinfo *cur;
746 int error;
747 char *cp, *hostname2 = NULL, *scope, *addr;
748 struct sockaddr_in6 *sin6;
749
750 /*
751 * if the servname does not match socktype/protocol, ignore it.
752 */
753 if (get_portmatch(pai, servname) != 0)
754 return 0;
755
756 afd = find_afd(pai->ai_family);
757 if (afd == NULL)
758 return 0;
759
760 if (!afd->a_scoped)
761 return explore_numeric(pai, hostname, servname, res, hostname);
762
763 cp = strchr(hostname, SCOPE_DELIMITER);
764 if (cp == NULL)
765 return explore_numeric(pai, hostname, servname, res, hostname);
766
767 /*
768 * Handle special case of <scoped_address><delimiter><scope id>
769 */
770 hostname2 = strdup(hostname);
771 if (hostname2 == NULL)
772 return EAI_MEMORY;
773 /* terminate at the delimiter */
774 hostname2[cp - hostname] = '\0';
775 addr = hostname2;
776 scope = cp + 1;
777
778 error = explore_numeric(pai, addr, servname, res, hostname);
779 if (error == 0) {
780 u_int32_t scopeid;
781
782 for (cur = *res; cur; cur = cur->ai_next) {
783 if (cur->ai_family != AF_INET6)
784 continue;
785 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
786 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
787 free(hostname2);
788 return(EAI_NODATA); /* XXX: is return OK? */
789 }
790 sin6->sin6_scope_id = scopeid;
791 }
792 }
793
794 free(hostname2);
795
796 return error;
797#endif
798}
799
800static int
801get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
802{
803 if ((pai->ai_flags & AI_CANONNAME) != 0) {
804 ai->ai_canonname = strdup(str);
805 if (ai->ai_canonname == NULL)
806 return EAI_MEMORY;
807 }
808 return 0;
809}
810
811static struct addrinfo *
812get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
813{
814 char *p;
815 struct addrinfo *ai;
816
817 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
818 + (afd->a_socklen));
819 if (ai == NULL)
820 return NULL;
821
822 memcpy(ai, pai, sizeof(struct addrinfo));
823 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
824 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
825 ai->ai_addr->sa_len = afd->a_socklen;
826 ai->ai_addrlen = afd->a_socklen;
827 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
828 p = (char *)(void *)(ai->ai_addr);
829 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
830 return ai;
831}
832
833static int
834get_portmatch(const struct addrinfo *ai, const char *servname)
835{
836
837 /* get_port does not touch first argument. when matchonly == 1. */
838 /* LINTED const cast */
839 return get_port((struct addrinfo *)ai, servname, 1);
840}
841
842static int
843get_port(struct addrinfo *ai, const char *servname, int matchonly)
844{
845 const char *proto;
846 struct servent *sp;
847 int port;
848 int allownumeric;
849 /* mutex is defined in getnameinfo.c */
850 extern void *__THREAD_NAME(serv_mutex);
851
852 if (servname == NULL)
853 return 0;
854 switch (ai->ai_family) {
855 case AF_INET:
856#ifdef AF_INET6
857 case AF_INET6:
858#endif
859 break;
860 default:
861 return 0;
862 }
863
864 switch (ai->ai_socktype) {
865 case SOCK_RAW:
866 return EAI_SERVICE;
867 case SOCK_DGRAM:
868 case SOCK_STREAM:
869 allownumeric = 1;
870 break;
871 case ANY:
872 allownumeric = 0;
873 break;
874 default:
875 return EAI_SOCKTYPE;
876 }
877
878 port = str2number(servname);
879 if (port >= 0) {
880 if (!allownumeric)
881 return EAI_SERVICE;
882 if (port < 0 || port > 65535)
883 return EAI_SERVICE;
884 port = htons(port);
885 } else {
886 if (ai->ai_flags & AI_NUMERICSERV)
887 return EAI_NONAME;
888
889 switch (ai->ai_socktype) {
890 case SOCK_DGRAM:
891 proto = "udp";
892 break;
893 case SOCK_STREAM:
894 proto = "tcp";
895 break;
896 default:
897 proto = NULL;
898 break;
899 }
900
901 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
902 sp = getservbyname(servname, proto);
903 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
904 if (sp == NULL)
905 return EAI_SERVICE;
906 port = sp->s_port;
907 }
908
909 if (!matchonly) {
910 switch (ai->ai_family) {
911 case AF_INET:
912 ((struct sockaddr_in *)(void *)
913 ai->ai_addr)->sin_port = port;
914 break;
915#ifdef INET6
916 case AF_INET6:
917 ((struct sockaddr_in6 *)(void *)
918 ai->ai_addr)->sin6_port = port;
919 break;
920#endif
921 }
922 }
923
924 return 0;
925}
926
927static const struct afd *
928find_afd(int af)
929{
930 const struct afd *afd;
931
932 if (af == PF_UNSPEC)
933 return NULL;
934 for (afd = afdl; afd->a_af; afd++) {
935 if (afd->a_af == af)
936 return afd;
937 }
938 return NULL;
939}
940
941#ifdef INET6
942/* convert a string to a scope identifier. XXX: IPv6 specific */
943static int
944ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
945{
946 u_long lscopeid;
947 struct in6_addr *a6 = &sin6->sin6_addr;
948 char *ep;
949
950 /* empty scopeid portion is invalid */
951 if (*scope == '\0')
952 return -1;
953
954 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
955 /*
956 * We currently assume a one-to-one mapping between links
957 * and interfaces, so we simply use interface indices for
958 * like-local scopes.
959 */
960 *scopeid = if_nametoindex(scope);
961 if (*scopeid == 0)
962 goto trynumeric;
963 return 0;
964 }
965
966 /* still unclear about literal, allow numeric only - placeholder */
967 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
968 goto trynumeric;
969 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
970 goto trynumeric;
971 else
972 goto trynumeric; /* global */
973
974 /* try to convert to a numeric id as a last resort */
975 trynumeric:
976 errno = 0;
977 lscopeid = strtoul(scope, &ep, 10);
978 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
979 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
980 return 0;
981 else
982 return -1;
983}
984#endif
985
986/* code duplicate with gethnamaddr.c */
987
988static const char AskedForGot[] =
989 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
990static FILE *hostf = NULL;
991
992static struct addrinfo *
993getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
994 const struct addrinfo *pai)
995{
996 struct addrinfo sentinel, *cur;
997 struct addrinfo ai;
998 const struct afd *afd;
999 char *canonname;
1000 const HEADER *hp;
1001 const u_char *cp;
1002 int n;
1003 const u_char *eom;
1004 char *bp, *ep;
1005 int type, class, ancount, qdcount;
1006 int haveanswer, had_error;
1007 char tbuf[MAXDNAME];
1008 int (*name_ok)(const char *);
1009 char hostbuf[8*1024];
1010
1011 memset(&sentinel, 0, sizeof(sentinel));
1012 cur = &sentinel;
1013
1014 canonname = NULL;
1015 eom = answer->buf + anslen;
1016 switch (qtype) {
1017 case T_A:
1018 case T_AAAA:
1019 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1020 name_ok = res_hnok;
1021 break;
1022 default:
1023 return (NULL); /* XXX should be abort() -- but that is illegal */
1024 }
1025 /*
1026 * find first satisfactory answer
1027 */
1028 hp = &answer->hdr;
1029 ancount = ntohs(hp->ancount);
1030 qdcount = ntohs(hp->qdcount);
1031 bp = hostbuf;
1032 ep = hostbuf + sizeof hostbuf;
1033 cp = answer->buf + HFIXEDSZ;
1034 if (qdcount != 1) {
1035 h_errno = NO_RECOVERY;
1036 return (NULL);
1037 }
1038 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1039 if ((n < 0) || !(*name_ok)(bp)) {
1040 h_errno = NO_RECOVERY;
1041 return (NULL);
1042 }
1043 cp += n + QFIXEDSZ;
1044 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1045 /* res_send() has already verified that the query name is the
1046 * same as the one we sent; this just gets the expanded name
1047 * (i.e., with the succeeding search-domain tacked on).
1048 */
1049 n = strlen(bp) + 1; /* for the \0 */
1050 if (n >= MAXHOSTNAMELEN) {
1051 h_errno = NO_RECOVERY;
1052 return (NULL);
1053 }
1054 canonname = bp;
1055 bp += n;
1056 /* The qname can be abbreviated, but h_name is now absolute. */
1057 qname = canonname;
1058 }
1059 haveanswer = 0;
1060 had_error = 0;
1061 while (ancount-- > 0 && cp < eom && !had_error) {
1062 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1063 if ((n < 0) || !(*name_ok)(bp)) {
1064 had_error++;
1065 continue;
1066 }
1067 cp += n; /* name */
1068 type = _getshort(cp);
1069 cp += INT16SZ; /* type */
1070 class = _getshort(cp);
1071 cp += INT16SZ + INT32SZ; /* class, TTL */
1072 n = _getshort(cp);
1073 cp += INT16SZ; /* len */
1074 if (class != C_IN) {
1075 /* XXX - debug? syslog? */
1076 cp += n;
1077 continue; /* XXX - had_error++ ? */
1078 }
1079 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1080 type == T_CNAME) {
1081 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1082 if ((n < 0) || !(*name_ok)(tbuf)) {
1083 had_error++;
1084 continue;
1085 }
1086 cp += n;
1087 /* Get canonical name. */
1088 n = strlen(tbuf) + 1; /* for the \0 */
1089 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1090 had_error++;
1091 continue;
1092 }
1093 strlcpy(bp, tbuf, ep - bp);
1094 canonname = bp;
1095 bp += n;
1096 continue;
1097 }
1098 if (qtype == T_ANY) {
1099 if (!(type == T_A || type == T_AAAA)) {
1100 cp += n;
1101 continue;
1102 }
1103 } else if (type != qtype) {
1104 if (type != T_KEY && type != T_SIG)
1105 syslog(LOG_NOTICE|LOG_AUTH,
1106 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1107 qname, p_class(C_IN), p_type(qtype),
1108 p_type(type));
1109 cp += n;
1110 continue; /* XXX - had_error++ ? */
1111 }
1112 switch (type) {
1113 case T_A:
1114 case T_AAAA:
1115 if (strcasecmp(canonname, bp) != 0) {
1116 syslog(LOG_NOTICE|LOG_AUTH,
1117 AskedForGot, canonname, bp);
1118 cp += n;
1119 continue; /* XXX - had_error++ ? */
1120 }
1121 if (type == T_A && n != INADDRSZ) {
1122 cp += n;
1123 continue;
1124 }
1125 if (type == T_AAAA && n != IN6ADDRSZ) {
1126 cp += n;
1127 continue;
1128 }
1129 if (type == T_AAAA) {
1130 struct in6_addr in6;
1131 memcpy(&in6, cp, IN6ADDRSZ);
1132 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1133 cp += n;
1134 continue;
1135 }
1136 }
1137 if (!haveanswer) {
1138 int nn;
1139
1140 canonname = bp;
1141 nn = strlen(bp) + 1; /* for the \0 */
1142 bp += nn;
1143 }
1144
1145 /* don't overwrite pai */
1146 ai = *pai;
1147 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1148 afd = find_afd(ai.ai_family);
1149 if (afd == NULL) {
1150 cp += n;
1151 continue;
1152 }
1153 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1154 if (cur->ai_next == NULL)
1155 had_error++;
1156 while (cur && cur->ai_next)
1157 cur = cur->ai_next;
1158 cp += n;
1159 break;
1160 default:
1161 abort(); /* XXX abort illegal in library */
1162 }
1163 if (!had_error)
1164 haveanswer++;
1165 }
1166 if (haveanswer) {
1167 if (!canonname)
1168 (void)get_canonname(pai, sentinel.ai_next, qname);
1169 else
1170 (void)get_canonname(pai, sentinel.ai_next, canonname);
1171 h_errno = NETDB_SUCCESS;
1172 return sentinel.ai_next;
1173 }
1174
1175 h_errno = NO_RECOVERY;
1176 return NULL;
1177}
1178
1179/*ARGSUSED*/
1180static struct addrinfo *
1181_dns_getaddrinfo(const char *name, const struct addrinfo *pai)
1182{
1183 struct addrinfo *ai;
1184 querybuf *buf, *buf2;
1185 struct addrinfo sentinel, *cur;
1186 struct res_target q, q2;
1187
1188 memset(&q, 0, sizeof(q2));
1189 memset(&q2, 0, sizeof(q2));
1190 memset(&sentinel, 0, sizeof(sentinel));
1191 cur = &sentinel;
1192
1193 buf = malloc(sizeof(*buf));
1194 if (buf == NULL) {
1195 h_errno = NETDB_INTERNAL;
1196 return NULL;
1197 }
1198 buf2 = malloc(sizeof(*buf2));
1199 if (buf2 == NULL) {
1200 free(buf);
1201 h_errno = NETDB_INTERNAL;
1202 return NULL;
1203 }
1204
1205 switch (pai->ai_family) {
1206 case AF_UNSPEC:
1207 /* prefer IPv6 */
1208 q.qclass = C_IN;
1209 q.qtype = T_AAAA;
1210 q.answer = buf->buf;
1211 q.anslen = sizeof(buf->buf);
1212 q.next = &q2;
1213 q2.qclass = C_IN;
1214 q2.qtype = T_A;
1215 q2.answer = buf2->buf;
1216 q2.anslen = sizeof(buf2->buf);
1217 break;
1218 case AF_INET:
1219 q.qclass = C_IN;
1220 q.qtype = T_A;
1221 q.answer = buf->buf;
1222 q.anslen = sizeof(buf->buf);
1223 break;
1224 case AF_INET6:
1225 q.qclass = C_IN;
1226 q.qtype = T_AAAA;
1227 q.answer = buf->buf;
1228 q.anslen = sizeof(buf->buf);
1229 break;
1230 default:
1231 free(buf);
1232 free(buf2);
1233 return NULL;
1234 }
1235 if (res_searchN(name, &q) < 0) {
1236 free(buf);
1237 free(buf2);
1238 return NULL;
1239 }
1240 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1241 if (ai) {
1242 cur->ai_next = ai;
1243 while (cur && cur->ai_next)
1244 cur = cur->ai_next;
1245 }
1246 if (q.next) {
1247 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1248 if (ai)
1249 cur->ai_next = ai;
1250 }
1251 free(buf);
1252 free(buf2);
1253 return sentinel.ai_next;
1254}
1255
1256static FILE *hostf;
1257
1258static void
1259_sethtent(void)
1260{
1261 if (!hostf)
1262 hostf = fopen(_PATH_HOSTS, "r" );
1263 else
1264 rewind(hostf);
1265}
1266
1267static void
1268_endhtent(void)
1269{
1270 if (hostf) {
1271 (void) fclose(hostf);
1272 hostf = NULL;
1273 }
1274}
1275
1276static struct addrinfo *
1277_gethtent(const char *name, const struct addrinfo *pai)
1278{
1279 char *p;
1280 char *cp, *tname, *cname;
1281 struct addrinfo hints, *res0, *res;
1282 int error;
1283 const char *addr;
1284 char hostbuf[8*1024];
1285
1286 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1287 return (NULL);
1288 again:
1289 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1290 return (NULL);
1291 if (*p == '#')
1292 goto again;
1293 if (!(cp = strpbrk(p, "#\n")))
1294 goto again;
1295 *cp = '\0';
1296 if (!(cp = strpbrk(p, " \t")))
1297 goto again;
1298 *cp++ = '\0';
1299 addr = p;
1300 /* if this is not something we're looking for, skip it. */
1301 cname = NULL;
1302 while (cp && *cp) {
1303 if (*cp == ' ' || *cp == '\t') {
1304 cp++;
1305 continue;
1306 }
1307 if (!cname)
1308 cname = cp;
1309 tname = cp;
1310 if ((cp = strpbrk(cp, " \t")) != NULL)
1311 *cp++ = '\0';
1312 if (strcasecmp(name, tname) == 0)
1313 goto found;
1314 }
1315 goto again;
1316
1317found:
1318 hints = *pai;
1319 hints.ai_flags = AI_NUMERICHOST;
1320 error = getaddrinfo(addr, NULL, &hints, &res0);
1321 if (error)
1322 goto again;
1323 for (res = res0; res; res = res->ai_next) {
1324 /* cover it up */
1325 res->ai_flags = pai->ai_flags;
1326
1327 if (pai->ai_flags & AI_CANONNAME) {
1328 if (get_canonname(pai, res, cname) != 0) {
1329 freeaddrinfo(res0);
1330 goto again;
1331 }
1332 }
1333 }
1334 return res0;
1335}
1336
1337/*ARGSUSED*/
1338static struct addrinfo *
1339_files_getaddrinfo(const char *name, const struct addrinfo *pai)
1340{
1341 struct addrinfo sentinel, *cur;
1342 struct addrinfo *p;
1343
1344 memset(&sentinel, 0, sizeof(sentinel));
1345 cur = &sentinel;
1346
1347 _sethtent();
1348 while ((p = _gethtent(name, pai)) != NULL) {
1349 cur->ai_next = p;
1350 while (cur && cur->ai_next)
1351 cur = cur->ai_next;
1352 }
1353 _endhtent();
1354
1355 return sentinel.ai_next;
1356}
1357
1358#ifdef YP
1359static char *__ypdomain;
1360
1361/*ARGSUSED*/
1362static struct addrinfo *
1363_yphostent(char *line, const struct addrinfo *pai)
1364{
1365 struct addrinfo sentinel, *cur;
1366 struct addrinfo hints, *res, *res0;
1367 int error;
1368 char *p = line;
1369 const char *addr, *canonname;
1370 char *nextline;
1371 char *cp;
1372
1373 addr = canonname = NULL;
1374
1375 memset(&sentinel, 0, sizeof(sentinel));
1376 cur = &sentinel;
1377
1378nextline:
1379 /* terminate line */
1380 cp = strchr(p, '\n');
1381 if (cp) {
1382 *cp++ = '\0';
1383 nextline = cp;
1384 } else
1385 nextline = NULL;
1386
1387 cp = strpbrk(p, " \t");
1388 if (cp == NULL) {
1389 if (canonname == NULL)
1390 return (NULL);
1391 else
1392 goto done;
1393 }
1394 *cp++ = '\0';
1395
1396 addr = p;
1397
1398 while (cp && *cp) {
1399 if (*cp == ' ' || *cp == '\t') {
1400 cp++;
1401 continue;
1402 }
1403 if (!canonname)
1404 canonname = cp;
1405 if ((cp = strpbrk(cp, " \t")) != NULL)
1406 *cp++ = '\0';
1407 }
1408
1409 hints = *pai;
1410 hints.ai_flags = AI_NUMERICHOST;
1411 error = getaddrinfo(addr, NULL, &hints, &res0);
1412 if (error == 0) {
1413 for (res = res0; res; res = res->ai_next) {
1414 /* cover it up */
1415 res->ai_flags = pai->ai_flags;
1416
1417 if (pai->ai_flags & AI_CANONNAME)
1418 (void)get_canonname(pai, res, canonname);
1419 }
1420 } else
1421 res0 = NULL;
1422 if (res0) {
1423 cur->ai_next = res0;
1424 while (cur && cur->ai_next)
1425 cur = cur->ai_next;
1426 }
1427
1428 if (nextline) {
1429 p = nextline;
1430 goto nextline;
1431 }
1432
1433done:
1434 return sentinel.ai_next;
1435}
1436
1437/*ARGSUSED*/
1438static struct addrinfo *
1439_yp_getaddrinfo(const char *name, const struct addrinfo *pai)
1440{
1441 struct addrinfo sentinel, *cur;
1442 struct addrinfo *ai = NULL;
1443 static char *__ypcurrent;
1444 int __ypcurrentlen, r;
1445
1446 memset(&sentinel, 0, sizeof(sentinel));
1447 cur = &sentinel;
1448
1449 if (!__ypdomain) {
1450 if (_yp_check(&__ypdomain) == 0)
1451 return NULL;
1452 }
1453 if (__ypcurrent)
1454 free(__ypcurrent);
1455 __ypcurrent = NULL;
1456
1457 /* hosts.byname is only for IPv4 (Solaris8) */
1458 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1459 r = yp_match(__ypdomain, "hosts.byname", name,
1460 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1461 if (r == 0) {
1462 struct addrinfo ai4;
1463
1464 ai4 = *pai;
1465 ai4.ai_family = AF_INET;
1466 ai = _yphostent(__ypcurrent, &ai4);
1467 if (ai) {
1468 cur->ai_next = ai;
1469 while (cur && cur->ai_next)
1470 cur = cur->ai_next;
1471 }
1472 }
1473 }
1474
1475 /* ipnodes.byname can hold both IPv4/v6 */
1476 r = yp_match(__ypdomain, "ipnodes.byname", name,
1477 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1478 if (r == 0) {
1479 ai = _yphostent(__ypcurrent, pai);
1480 if (ai) {
1481 cur->ai_next = ai;
1482 while (cur && cur->ai_next)
1483 cur = cur->ai_next;
1484 }
1485 }
1486
1487 return sentinel.ai_next;
1488}
1489#endif
1490
1491
1492/* resolver logic */
1493
1494extern const char *__hostalias(const char *);
1495extern int h_errno;
1496extern int res_opt(int, u_char *, int, int);
1497
1498/*
1499 * Formulate a normal query, send, and await answer.
1500 * Returned answer is placed in supplied buffer "answer".
1501 * Perform preliminary check of answer, returning success only
1502 * if no error is indicated and the answer count is nonzero.
1503 * Return the size of the response on success, -1 on error.
1504 * Error number is left in h_errno.
1505 *
1506 * Caller must parse answer and determine whether it answers the question.
1507 */
1508static int
1509res_queryN(const char *name, struct res_target *target)
1510{
1511 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1512 u_char *buf;
1513 HEADER *hp;
1514 int n;
1515 struct res_target *t;
1516 int rcode;
1517 int ancount;
1518
1519 buf = malloc(MAXPACKET);
1520 if (buf == NULL) {
1521 h_errno = NETDB_INTERNAL;
1522 return (-1);
1523 }
1524
1525 rcode = NOERROR;
1526 ancount = 0;
1527
1528 if (_res_init(0) == -1) {
1529 h_errno = NETDB_INTERNAL;
1530 free(buf);
1531 return (-1);
1532 }
1533
1534 for (t = target; t; t = t->next) {
1535 int class, type;
1536 u_char *answer;
1537 int anslen;
1538
1539 hp = (HEADER *)(void *)t->answer;
1540 hp->rcode = NOERROR; /* default */
1541
1542 /* make it easier... */
1543 class = t->qclass;
1544 type = t->qtype;
1545 answer = t->answer;
1546 anslen = t->anslen;
1547#ifdef DEBUG
1548 if (_resp->options & RES_DEBUG)
1549 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1550#endif
1551
1552 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1553 buf, MAXPACKET);
1554 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1555 n = res_opt(n, buf, MAXPACKET, anslen);
1556 if (n <= 0) {
1557#ifdef DEBUG
1558 if (_resp->options & RES_DEBUG)
1559 printf(";; res_query: mkquery failed\n");
1560#endif
1561 h_errno = NO_RECOVERY;
1562 free(buf);
1563 return (n);
1564 }
1565 n = res_send(buf, n, answer, anslen);
1566#if 0
1567 if (n < 0) {
1568#ifdef DEBUG
1569 if (_resp->options & RES_DEBUG)
1570 printf(";; res_query: send error\n");
1571#endif
1572 h_errno = TRY_AGAIN;
1573 free(buf);
1574 return (n);
1575 }
1576#endif
1577
1578 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1579 rcode = hp->rcode; /* record most recent error */
1580#ifdef DEBUG
1581 if (_resp->options & RES_DEBUG)
1582 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1583 ntohs(hp->ancount));
1584#endif
1585 continue;
1586 }
1587
1588 ancount += ntohs(hp->ancount);
1589
1590 t->n = n;
1591 }
1592
1593 if (ancount == 0) {
1594 switch (rcode) {
1595 case NXDOMAIN:
1596 h_errno = HOST_NOT_FOUND;
1597 break;
1598 case SERVFAIL:
1599 h_errno = TRY_AGAIN;
1600 break;
1601 case NOERROR:
1602 h_errno = NO_DATA;
1603 break;
1604 case FORMERR:
1605 case NOTIMP:
1606 case REFUSED:
1607 default:
1608 h_errno = NO_RECOVERY;
1609 break;
1610 }
1611 free(buf);
1612 return (-1);
1613 }
1614 free(buf);
1615 return (ancount);
1616}
1617
1618/*
1619 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1620 * Return the size of the response on success, -1 on error.
1621 * If enabled, implement search rules until answer or unrecoverable failure
1622 * is detected. Error code, if any, is left in h_errno.
1623 */
1624static int
1625res_searchN(const char *name, struct res_target *target)
1626{
1627 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1628 const char *cp, * const *domain;
1629 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1630 u_int dots;
1631 int trailing_dot, ret, saved_herrno;
1632 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1633
1634 if (_res_init(0) == -1) {
1635 h_errno = NETDB_INTERNAL;
1636 return (-1);
1637 }
1638
1639 errno = 0;
1640 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1641 dots = 0;
1642 for (cp = name; *cp; cp++)
1643 dots += (*cp == '.');
1644 trailing_dot = 0;
1645 if (cp > name && *--cp == '.')
1646 trailing_dot++;
1647
1648 /*
1649 * if there aren't any dots, it could be a user-level alias
1650 */
1651 if (!dots && (cp = __hostalias(name)) != NULL)
1652 return (res_queryN(cp, target));
1653
1654 /*
1655 * If there are dots in the name already, let's just give it a try
1656 * 'as is'. The threshold can be set with the "ndots" option.
1657 */
1658 saved_herrno = -1;
1659 if (dots >= _resp->ndots) {
1660 ret = res_querydomainN(name, NULL, target);
1661 if (ret > 0)
1662 return (ret);
1663 saved_herrno = h_errno;
1664 tried_as_is++;
1665 }
1666
1667 /*
1668 * We do at least one level of search if
1669 * - there is no dot and RES_DEFNAME is set, or
1670 * - there is at least one dot, there is no trailing dot,
1671 * and RES_DNSRCH is set.
1672 */
1673 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1674 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1675 int done = 0;
1676
1677 for (domain = (const char * const *)_resp->dnsrch;
1678 *domain && !done;
1679 domain++) {
1680
1681 ret = res_querydomainN(name, *domain, target);
1682 if (ret > 0)
1683 return (ret);
1684
1685 /*
1686 * If no server present, give up.
1687 * If name isn't found in this domain,
1688 * keep trying higher domains in the search list
1689 * (if that's enabled).
1690 * On a NO_DATA error, keep trying, otherwise
1691 * a wildcard entry of another type could keep us
1692 * from finding this entry higher in the domain.
1693 * If we get some other error (negative answer or
1694 * server failure), then stop searching up,
1695 * but try the input name below in case it's
1696 * fully-qualified.
1697 */
1698 if (errno == ECONNREFUSED) {
1699 h_errno = TRY_AGAIN;
1700 return (-1);
1701 }
1702
1703 switch (h_errno) {
1704 case NO_DATA:
1705 got_nodata++;
1706 /* FALLTHROUGH */
1707 case HOST_NOT_FOUND:
1708 /* keep trying */
1709 break;
1710 case TRY_AGAIN:
1711 if (hp->rcode == SERVFAIL) {
1712 /* try next search element, if any */
1713 got_servfail++;
1714 break;
1715 }
1716 /* FALLTHROUGH */
1717 default:
1718 /* anything else implies that we're done */
1719 done++;
1720 }
1721 /*
1722 * if we got here for some reason other than DNSRCH,
1723 * we only wanted one iteration of the loop, so stop.
1724 */
1725 if (!(_resp->options & RES_DNSRCH))
1726 done++;
1727 }
1728 }
1729
1730 /*
1731 * if we have not already tried the name "as is", do that now.
1732 * note that we do this regardless of how many dots were in the
1733 * name or whether it ends with a dot.
1734 */
1735 if (!tried_as_is) {
1736 ret = res_querydomainN(name, NULL, target);
1737 if (ret > 0)
1738 return (ret);
1739 }
1740
1741 /*
1742 * if we got here, we didn't satisfy the search.
1743 * if we did an initial full query, return that query's h_errno
1744 * (note that we wouldn't be here if that query had succeeded).
1745 * else if we ever got a nodata, send that back as the reason.
1746 * else send back meaningless h_errno, that being the one from
1747 * the last DNSRCH we did.
1748 */
1749 if (saved_herrno != -1)
1750 h_errno = saved_herrno;
1751 else if (got_nodata)
1752 h_errno = NO_DATA;
1753 else if (got_servfail)
1754 h_errno = TRY_AGAIN;
1755 return (-1);
1756}
1757
1758/*
1759 * Perform a call on res_query on the concatenation of name and domain,
1760 * removing a trailing dot from name if domain is NULL.
1761 */
1762static int
1763res_querydomainN(const char *name, const char *domain,
1764 struct res_target *target)
1765{
1766 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1767 char nbuf[MAXDNAME];
1768 const char *longname = nbuf;
1769 size_t n, d;
1770
1771 if (_res_init(0) == -1) {
1772 h_errno = NETDB_INTERNAL;
1773 return (-1);
1774 }
1775#ifdef DEBUG
1776 if (_resp->options & RES_DEBUG)
1777 printf(";; res_querydomain(%s, %s)\n",
1778 name, domain?domain:"<Nil>");
1779#endif
1780 if (domain == NULL) {
1781 /*
1782 * Check for trailing '.';
1783 * copy without '.' if present.
1784 */
1785 n = strlen(name);
1786 if (n >= MAXDNAME) {
1787 h_errno = NO_RECOVERY;
1788 return (-1);
1789 }
1790 if (n > 0 && name[--n] == '.') {
1791 strlcpy(nbuf, name, n + 1);
1792 } else
1793 longname = name;
1794 } else {
1795 n = strlen(name);
1796 d = strlen(domain);
1797 if (n + d + 1 >= MAXDNAME) {
1798 h_errno = NO_RECOVERY;
1799 return (-1);
1800 }
1801 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1802 }
1803 return (res_queryN(longname, target));
1804}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
new file mode 100644
index 0000000000..51377dbc21
--- /dev/null
+++ b/src/lib/libc/net/gethostbyname.3
@@ -0,0 +1,296 @@
1.\" $OpenBSD: gethostbyname.3,v 1.22 2004/03/14 18:05:37 jmc Exp $
2.\"
3.\" Copyright (c) 1983, 1987, 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 March 13, 1997
31.Dt GETHOSTBYNAME 3
32.Os
33.Sh NAME
34.Nm gethostbyname ,
35.Nm gethostbyname2 ,
36.Nm gethostbyaddr ,
37.Nm gethostent ,
38.Nm sethostent ,
39.Nm endhostent ,
40.Nm hstrerror ,
41.Nm herror
42.Nd get network host entry
43.Sh SYNOPSIS
44.Fd #include <netdb.h>
45.Fd extern int h_errno;
46.Ft struct hostent *
47.Fn gethostbyname "const char *name"
48.Ft struct hostent *
49.Fn gethostbyname2 "const char *name" "int af"
50.Ft struct hostent *
51.Fn gethostbyaddr "const char *addr" "int len" "int af"
52.Ft struct hostent *
53.Fn gethostent void
54.Ft void
55.Fn sethostent "int stayopen"
56.Ft void
57.Fn endhostent void
58.Ft void
59.Fn herror "const char *string"
60.Ft const char *
61.Fn hstrerror "int err"
62.Sh DESCRIPTION
63The
64.Fn gethostbyname ,
65.Fn gethostbyname2
66and
67.Fn gethostbyaddr
68functions each return a pointer to an object with the following structure
69describing an internet host referenced by name or by address, respectively.
70This structure contains either information obtained from the name server (i.e.,
71.Xr resolver 3
72and
73.Xr named 8 ) ,
74broken-out fields from a line in
75.Pa /etc/hosts ,
76or database entries supplied by the
77.Xr yp 8
78system.
79.Xr resolv.conf 5
80describes how the particular database is chosen.
81.Bd -literal
82struct hostent {
83 char *h_name; /* official name of host */
84 char **h_aliases; /* alias list */
85 int h_addrtype; /* host address type */
86 int h_length; /* length of address */
87 char **h_addr_list; /* list of addresses from name server */
88};
89#define h_addr h_addr_list[0] /* address, for backward compatibility */
90.Ed
91.Pp
92The members of this structure are:
93.Bl -tag -width h_addr_list
94.It Fa h_name
95Official name of the host.
96.It Fa h_aliases
97A NULL-terminated array of alternate names for the host.
98.It Fa h_addrtype
99The type of address being returned.
100.It Fa h_length
101The length, in bytes, of the address.
102.It Fa h_addr_list
103A zero-terminated array of network addresses for the host.
104Host addresses are returned in network byte order.
105.It Fa h_addr
106The first address in
107.Fa h_addr_list ;
108this is for backward compatibility.
109.El
110.Pp
111The function
112.Fn gethostbyname
113will search for the named host in the current domain and its parents
114using the search lookup semantics detailed in
115.Xr resolv.conf 5
116and
117.Xr hostname 7 .
118.Pp
119.Fn gethostbyname2
120is an advanced form of
121.Fn gethostbyname
122which allows lookups in address families other than
123.Dv AF_INET .
124Currently, the only supported address family besides
125.Dv AF_INET
126is
127.Dv AF_INET6 .
128.Pp
129The
130.Fn gethostbyaddr
131function will search for the specified address of length
132.Fa len
133in the address family
134.Fa af .
135The only address family currently supported is
136.Dv AF_INET .
137.Pp
138The
139.Fn sethostent
140function may be used to request the use of a connected
141.Tn TCP
142socket for queries.
143If the
144.Fa stayopen
145flag is non-zero,
146this sets the option to send all queries to the name server using
147.Tn TCP
148and to retain the connection after each call to
149.Fn gethostbyname
150or
151.Fn gethostbyaddr .
152Otherwise, queries are performed using
153.Tn UDP
154datagrams.
155.Pp
156The
157.Fn endhostent
158function closes the
159.Tn TCP
160connection.
161.Pp
162The
163.Fn herror
164function prints an error message describing the failure.
165If its argument
166.Fa string
167is non-null,
168it is prepended to the message string and separated from it by a colon
169.Pq Ql \&:
170and a space.
171The error message is printed with a trailing newline.
172The contents of the error message is the same as that returned by
173.Fn hstrerror
174with argument
175.Fa h_errno .
176.Sh ENVIRONMENT
177.Bl -tag -width HOSTALIASES
178.It HOSTALIASES
179A file containing local host aliases.
180See
181.Xr hostname 7
182for more information.
183.It RES_OPTIONS
184A list of options to override the resolver's internal defaults.
185See
186.Xr resolver 3
187for more information.
188.El
189.Sh FILES
190.Bl -tag -width /etc/resolv.conf -compact
191.It Pa /etc/hosts
192.It Pa /etc/resolv.conf
193.El
194.Sh DIAGNOSTICS
195Error return status from
196.Fn gethostbyname ,
197.Fn gethostbyname2 ,
198and
199.Fn gethostbyaddr
200is indicated by return of a null pointer.
201The external integer
202.Va h_errno
203may then be checked to see whether this is a temporary failure
204or an invalid or unknown host.
205.Pp
206The variable
207.Va h_errno
208can have the following values:
209.Bl -tag -width HOST_NOT_FOUND
210.It Dv HOST_NOT_FOUND
211No such host is known.
212.It Dv TRY_AGAIN
213This is usually a temporary error
214and means that the local server did not receive
215a response from an authoritative server.
216A retry at some later time may succeed.
217.It Dv NO_RECOVERY
218Some unexpected server failure was encountered.
219This is a non-recoverable error.
220.It Dv NO_DATA
221The requested name is valid but does not have an IP address;
222this is not a temporary error.
223This means that the name is known to the name server but there is no address
224associated with this name.
225Another type of request to the name server using this domain name
226will result in an answer;
227for example, a mail-forwarder may be registered for this domain.
228.It Dv NETDB_INTERNAL
229An internal error occurred.
230This may occurs when an address family other than
231.Dv AF_INET
232or
233.Dv AF_INET6
234is specified or when a resource is unable to be allocated.
235.It Dv NETDB_SUCCESS
236The function completed successfully.
237.El
238.Sh SEE ALSO
239.Xr getaddrinfo 3 ,
240.Xr getnameinfo 3 ,
241.Xr resolver 3 ,
242.Xr hosts 5 ,
243.Xr resolv.conf 5 ,
244.Xr hostname 7 ,
245.Xr named 8
246.Sh HISTORY
247The
248.Fn herror
249function appeared in
250.Bx 4.3 .
251The
252.Fn endhostent ,
253.Fn gethostbyaddr ,
254.Fn gethostbyname ,
255.Fn gethostent ,
256and
257.Fn sethostent
258functions appeared in
259.Bx 4.2 .
260.Sh CAVEATS
261If the search routines in
262.Xr resolv.conf 5
263decide to read the
264.Pa /etc/hosts
265file,
266.Fn gethostent
267and other functions will
268read the next line of the file,
269re-opening the file if necessary.
270.Pp
271The
272.Fn sethostent
273function opens and/or rewinds the file
274.Pa /etc/hosts .
275If the
276.Fa stayopen
277argument is non-zero, the file will not be closed after each call to
278.Fn gethostbyname ,
279.Fn gethostbyname2 ,
280or
281.Fn gethostbyaddr .
282.Pp
283The
284.Fn endhostent
285function closes the file.
286.Sh BUGS
287These functions use static data storage;
288if the data is needed for future use, it should be
289copied before any subsequent calls overwrite it.
290Only the Internet
291address formats are currently understood.
292.Pp
293YP does not support any address families other than
294.Dv AF_INET
295and uses
296the traditional database format.
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
new file mode 100644
index 0000000000..c643f2382a
--- /dev/null
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,1142 @@
1/*-
2 * Copyright (c) 1985, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 * -
29 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
30 *
31 * Permission to use, copy, modify, and distribute this software for any
32 * purpose with or without fee is hereby granted, provided that the above
33 * copyright notice and this permission notice appear in all copies, and that
34 * the name of Digital Equipment Corporation not be used in advertising or
35 * publicity pertaining to distribution of the document or software without
36 * specific, written prior permission.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
39 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
41 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
42 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
43 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
44 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 * SOFTWARE.
46 * -
47 * --Copyright--
48 */
49
50#if defined(LIBC_SCCS) && !defined(lint)
51static const char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.61 2005/03/30 02:58:28 tedu Exp $";
52#endif /* LIBC_SCCS and not lint */
53
54#include <sys/param.h>
55#include <sys/socket.h>
56#include <netinet/in.h>
57#include <arpa/inet.h>
58#include <arpa/nameser.h>
59#include <netdb.h>
60#include <resolv.h>
61#include <stdio.h>
62#include <ctype.h>
63#include <errno.h>
64#include <string.h>
65#include <syslog.h>
66#include <stdlib.h>
67#ifdef YP
68#include <rpc/rpc.h>
69#include <rpcsvc/yp.h>
70#include <rpcsvc/ypclnt.h>
71#include "ypinternal.h"
72#endif
73#include "thread_private.h"
74
75#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
76
77#define MAXALIASES 35
78#define MAXADDRS 35
79
80static char *h_addr_ptrs[MAXADDRS + 1];
81
82#ifdef YP
83static char *__ypdomain;
84#endif
85
86static struct hostent host;
87static char *host_aliases[MAXALIASES];
88static char hostbuf[BUFSIZ+1];
89static union {
90 struct in_addr _host_in_addr;
91 u_char _host_addr[16]; /* IPv4 or IPv6 */
92} _host_addr_u;
93#define host_addr _host_addr_u._host_addr
94static FILE *hostf = NULL;
95static int stayopen = 0;
96
97static void map_v4v6_address(const char *src, char *dst);
98static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
99
100#ifdef RESOLVSORT
101static void addrsort(char **, int);
102#endif
103
104int _hokchar(const char *);
105
106static const char AskedForGot[] =
107 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
108
109#define MAXPACKET (64*1024)
110
111typedef union {
112 HEADER hdr;
113 u_char buf[MAXPACKET];
114} querybuf;
115
116typedef union {
117 int32_t al;
118 char ac;
119} align;
120
121static struct hostent *getanswer(const querybuf *, int, const char *, int);
122
123extern int h_errno;
124
125int
126_hokchar(const char *p)
127{
128 char c;
129
130 /*
131 * Many people do not obey RFC 822 and 1035. The valid
132 * characters are a-z, A-Z, 0-9, '-' and . But the others
133 * tested for below can happen, and we must be more permissive
134 * than the resolver until those idiots clean up their act.
135 * We let '/' through, but not '..'
136 */
137 while ((c = *p++)) {
138 if (('a' <= c && c <= 'z') ||
139 ('A' <= c && c <= 'Z') ||
140 ('0' <= c && c <= '9'))
141 continue;
142 if (strchr("-_/", c))
143 continue;
144 if (c == '.' && *p != '.')
145 continue;
146 return 0;
147 }
148 return 1;
149}
150
151static struct hostent *
152getanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
153{
154 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
155 const HEADER *hp;
156 const u_char *cp, *eom;
157 char tbuf[MAXDNAME];
158 char *bp, **ap, **hap, *ep;
159 int type, class, ancount, qdcount, n;
160 int haveanswer, had_error, toobig = 0;
161 const char *tname;
162 int (*name_ok)(const char *);
163
164 tname = qname;
165 host.h_name = NULL;
166 eom = answer->buf + anslen;
167 switch (qtype) {
168 case T_A:
169 case T_AAAA:
170#ifdef USE_RESOLV_NAME_OK
171 name_ok = res_hnok;
172 break;
173#endif
174 case T_PTR:
175#ifdef USE_RESOLV_NAME_OK
176 name_ok = res_dnok;
177#else
178 name_ok = _hokchar;
179#endif
180 break;
181 default:
182 return (NULL);
183 }
184 /*
185 * find first satisfactory answer
186 */
187 hp = &answer->hdr;
188 ancount = ntohs(hp->ancount);
189 qdcount = ntohs(hp->qdcount);
190 bp = hostbuf;
191 ep = hostbuf + sizeof hostbuf;
192 cp = answer->buf + HFIXEDSZ;
193 if (qdcount != 1) {
194 h_errno = NO_RECOVERY;
195 return (NULL);
196 }
197 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
198 if ((n < 0) || !(*name_ok)(bp)) {
199 h_errno = NO_RECOVERY;
200 return (NULL);
201 }
202 cp += n + QFIXEDSZ;
203 if (qtype == T_A || qtype == T_AAAA) {
204 /* res_send() has already verified that the query name is the
205 * same as the one we sent; this just gets the expanded name
206 * (i.e., with the succeeding search-domain tacked on).
207 */
208 n = strlen(bp) + 1; /* for the \0 */
209 host.h_name = bp;
210 bp += n;
211 /* The qname can be abbreviated, but h_name is now absolute. */
212 qname = host.h_name;
213 }
214 ap = host_aliases;
215 *ap = NULL;
216 host.h_aliases = host_aliases;
217 hap = h_addr_ptrs;
218 *hap = NULL;
219 host.h_addr_list = h_addr_ptrs;
220 haveanswer = 0;
221 had_error = 0;
222 while (ancount-- > 0 && cp < eom && !had_error) {
223 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
224 if ((n < 0) || !(*name_ok)(bp)) {
225 had_error++;
226 continue;
227 }
228 cp += n; /* name */
229 if (cp >= eom)
230 break;
231 type = _getshort(cp);
232 cp += INT16SZ; /* type */
233 if (cp >= eom)
234 break;
235 class = _getshort(cp);
236 cp += INT16SZ + INT32SZ; /* class, TTL */
237 if (cp >= eom)
238 break;
239 n = _getshort(cp);
240 cp += INT16SZ; /* len */
241 if (cp >= eom)
242 break;
243 if (type == T_SIG) {
244 /* XXX - ignore signatures as we don't use them yet */
245 cp += n;
246 continue;
247 }
248 if (class != C_IN) {
249 /* XXX - debug? syslog? */
250 cp += n;
251 continue; /* XXX - had_error++ ? */
252 }
253 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
254 if (ap >= &host_aliases[MAXALIASES-1])
255 continue;
256 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
257 if ((n < 0) || !(*name_ok)(tbuf)) {
258 had_error++;
259 continue;
260 }
261 cp += n;
262 /* Store alias. */
263 *ap++ = bp;
264 n = strlen(bp) + 1; /* for the \0 */
265 bp += n;
266 /* Get canonical name. */
267 n = strlen(tbuf) + 1; /* for the \0 */
268 if (n > ep - bp) {
269 had_error++;
270 continue;
271 }
272 strlcpy(bp, tbuf, ep - bp);
273 host.h_name = bp;
274 bp += n;
275 continue;
276 }
277 if (qtype == T_PTR && type == T_CNAME) {
278 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
279#ifdef USE_RESOLV_NAME_OK
280 if ((n < 0) || !res_hnok(tbuf)) {
281#else
282 if ((n < 0) || !_hokchar(tbuf)) {
283#endif
284 had_error++;
285 continue;
286 }
287 cp += n;
288 /* Get canonical name. */
289 n = strlen(tbuf) + 1; /* for the \0 */
290 if (n > ep - bp) {
291 had_error++;
292 continue;
293 }
294 strlcpy(bp, tbuf, ep - bp);
295 tname = bp;
296 bp += n;
297 continue;
298 }
299 if (type != qtype) {
300 syslog(LOG_NOTICE|LOG_AUTH,
301 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
302 qname, p_class(C_IN), p_type(qtype),
303 p_type(type));
304 cp += n;
305 continue; /* XXX - had_error++ ? */
306 }
307 switch (type) {
308 case T_PTR:
309 if (strcasecmp(tname, bp) != 0) {
310 syslog(LOG_NOTICE|LOG_AUTH,
311 AskedForGot, qname, bp);
312 cp += n;
313 continue; /* XXX - had_error++ ? */
314 }
315 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
316#ifdef USE_RESOLV_NAME_OK
317 if ((n < 0) || !res_hnok(bp)) {
318#else
319 if ((n < 0) || !_hokchar(bp)) {
320#endif
321 had_error++;
322 break;
323 }
324#if MULTI_PTRS_ARE_ALIASES
325 cp += n;
326 if (!haveanswer)
327 host.h_name = bp;
328 else if (ap < &host_aliases[MAXALIASES-1])
329 *ap++ = bp;
330 else
331 n = -1;
332 if (n != -1) {
333 n = strlen(bp) + 1; /* for the \0 */
334 bp += n;
335 }
336 break;
337#else
338 host.h_name = bp;
339 if (_resp->options & RES_USE_INET6) {
340 n = strlen(bp) + 1; /* for the \0 */
341 bp += n;
342 map_v4v6_hostent(&host, &bp, ep);
343 }
344 h_errno = NETDB_SUCCESS;
345 return (&host);
346#endif
347 case T_A:
348 case T_AAAA:
349 if (strcasecmp(host.h_name, bp) != 0) {
350 syslog(LOG_NOTICE|LOG_AUTH,
351 AskedForGot, host.h_name, bp);
352 cp += n;
353 continue; /* XXX - had_error++ ? */
354 }
355 if (n != host.h_length) {
356 cp += n;
357 continue;
358 }
359 if (type == T_AAAA) {
360 struct in6_addr in6;
361 memcpy(&in6, cp, IN6ADDRSZ);
362 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
363 cp += n;
364 continue;
365 }
366 }
367 if (!haveanswer) {
368 int nn;
369
370 host.h_name = bp;
371 nn = strlen(bp) + 1; /* for the \0 */
372 bp += nn;
373 }
374
375 bp += sizeof(align) - ((u_long)bp % sizeof(align));
376
377 if (bp + n >= &hostbuf[sizeof hostbuf]) {
378#ifdef DEBUG
379 if (_resp->options & RES_DEBUG)
380 printf("size (%d) too big\n", n);
381#endif
382 had_error++;
383 continue;
384 }
385 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
386 if (!toobig++)
387#ifdef DEBUG
388 if (_resp->options & RES_DEBUG)
389 printf("Too many addresses (%d)\n", MAXADDRS);
390#endif
391 cp += n;
392 continue;
393 }
394 bcopy(cp, *hap++ = bp, n);
395 bp += n;
396 cp += n;
397 break;
398 }
399 if (!had_error)
400 haveanswer++;
401 }
402 if (haveanswer) {
403 *ap = NULL;
404 *hap = NULL;
405# if defined(RESOLVSORT)
406 /*
407 * Note: we sort even if host can take only one address
408 * in its return structures - should give it the "best"
409 * address in that case, not some random one
410 */
411 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
412 addrsort(h_addr_ptrs, haveanswer);
413# endif /*RESOLVSORT*/
414 if (!host.h_name) {
415 n = strlen(qname) + 1; /* for the \0 */
416 if (n > ep - bp)
417 goto try_again;
418 strlcpy(bp, qname, ep - bp);
419 host.h_name = bp;
420 bp += n;
421 }
422 if (_resp->options & RES_USE_INET6)
423 map_v4v6_hostent(&host, &bp, ep);
424 h_errno = NETDB_SUCCESS;
425 return (&host);
426 }
427 try_again:
428 h_errno = TRY_AGAIN;
429 return (NULL);
430}
431
432#ifdef notyet
433/*
434 * XXX This is an extremely bogus implementation.
435 *
436 * FreeBSD has this interface:
437 * int gethostbyaddr_r(const char *addr, int len, int type,
438 * struct hostent *result, struct hostent_data *buffer)
439 */
440
441struct hostent *
442gethostbyname_r(const char *name, struct hostent *hp, char *buf, int buflen,
443 int *errorp)
444{
445 struct hostent *res;
446
447 res = gethostbyname(name);
448 *errorp = h_errno;
449 if (res == NULL)
450 return NULL;
451 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
452 return hp;
453}
454
455/*
456 * XXX This is an extremely bogus implementation.
457 */
458struct hostent *
459gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
460 char *buf, int buflen, int *errorp)
461{
462 struct hostent * res;
463
464 res = gethostbyaddr(addr, len, af);
465 *errorp = h_errno;
466 if (res == NULL)
467 return NULL;
468 memcpy(he, res, sizeof *he); /* XXX not sufficient */
469 return he;
470}
471
472/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
473#endif
474
475struct hostent *
476gethostbyname(const char *name)
477{
478 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
479 struct hostent *hp;
480 extern struct hostent *_gethtbyname2(const char *, int);
481
482 if (_res_init(0) == -1)
483 hp = _gethtbyname2(name, AF_INET);
484
485 else if (_resp->options & RES_USE_INET6) {
486 hp = gethostbyname2(name, AF_INET6);
487 if (hp == NULL)
488 hp = gethostbyname2(name, AF_INET);
489 }
490 else
491 hp = gethostbyname2(name, AF_INET);
492 return hp;
493}
494
495struct hostent *
496gethostbyname2(const char *name, int af)
497{
498 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
499 querybuf *buf;
500 const char *cp;
501 char *bp, *ep;
502 int n, size, type, i;
503 struct hostent *hp;
504 char lookups[MAXDNSLUS];
505 extern struct hostent *_gethtbyname2(const char *, int);
506 extern struct hostent *_yp_gethtbyname(const char *);
507
508 if (_res_init(0) == -1)
509 return (_gethtbyname2(name, af));
510
511 switch (af) {
512 case AF_INET:
513 size = INADDRSZ;
514 type = T_A;
515 break;
516 case AF_INET6:
517 size = IN6ADDRSZ;
518 type = T_AAAA;
519 break;
520 default:
521 h_errno = NETDB_INTERNAL;
522 errno = EAFNOSUPPORT;
523 return (NULL);
524 }
525
526 host.h_addrtype = af;
527 host.h_length = size;
528
529 /*
530 * if there aren't any dots, it could be a user-level alias.
531 * this is also done in res_query() since we are not the only
532 * function that looks up host names.
533 */
534 if (!strchr(name, '.') && (cp = __hostalias(name)))
535 name = cp;
536
537 /*
538 * disallow names consisting only of digits/dots, unless
539 * they end in a dot.
540 */
541 if (isdigit(name[0]))
542 for (cp = name;; ++cp) {
543 if (!*cp) {
544 if (*--cp == '.')
545 break;
546 /*
547 * All-numeric, no dot at the end.
548 * Fake up a hostent as if we'd actually
549 * done a lookup.
550 */
551 if (inet_pton(af, name, host_addr) <= 0) {
552 h_errno = HOST_NOT_FOUND;
553 return (NULL);
554 }
555 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
556 bp = hostbuf + MAXHOSTNAMELEN;
557 ep = hostbuf + sizeof(hostbuf);
558 host.h_name = hostbuf;
559 host.h_aliases = host_aliases;
560 host_aliases[0] = NULL;
561 h_addr_ptrs[0] = (char *)host_addr;
562 h_addr_ptrs[1] = NULL;
563 host.h_addr_list = h_addr_ptrs;
564 if (_resp->options & RES_USE_INET6)
565 map_v4v6_hostent(&host, &bp, ep);
566 h_errno = NETDB_SUCCESS;
567 return (&host);
568 }
569 if (!isdigit(*cp) && *cp != '.')
570 break;
571 }
572 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
573 name[0] == ':')
574 for (cp = name;; ++cp) {
575 if (!*cp) {
576 if (*--cp == '.')
577 break;
578 /*
579 * All-IPv6-legal, no dot at the end.
580 * Fake up a hostent as if we'd actually
581 * done a lookup.
582 */
583 if (inet_pton(af, name, host_addr) <= 0) {
584 h_errno = HOST_NOT_FOUND;
585 return (NULL);
586 }
587 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
588 bp = hostbuf + MAXHOSTNAMELEN;
589 ep = hostbuf + sizeof(hostbuf);
590 host.h_name = hostbuf;
591 host.h_aliases = host_aliases;
592 host_aliases[0] = NULL;
593 h_addr_ptrs[0] = (char *)host_addr;
594 h_addr_ptrs[1] = NULL;
595 host.h_addr_list = h_addr_ptrs;
596 h_errno = NETDB_SUCCESS;
597 return (&host);
598 }
599 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
600 break;
601 }
602
603 bcopy(_resp->lookups, lookups, sizeof lookups);
604 if (lookups[0] == '\0')
605 strlcpy(lookups, "bf", sizeof lookups);
606
607 hp = (struct hostent *)NULL;
608 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
609 switch (lookups[i]) {
610#ifdef YP
611 case 'y':
612 /* YP only supports AF_INET. */
613 if (af == AF_INET)
614 hp = _yp_gethtbyname(name);
615 break;
616#endif
617 case 'b':
618 buf = malloc(sizeof(*buf));
619 if (buf == NULL)
620 break;
621 if ((n = res_search(name, C_IN, type, buf->buf,
622 sizeof(buf->buf))) < 0) {
623 free(buf);
624#ifdef DEBUG
625 if (_resp->options & RES_DEBUG)
626 printf("res_search failed\n");
627#endif
628 break;
629 }
630 hp = getanswer(buf, n, name, type);
631 free(buf);
632 break;
633 case 'f':
634 hp = _gethtbyname2(name, af);
635 break;
636 }
637 }
638 /* XXX h_errno not correct in all cases... */
639 return (hp);
640}
641
642struct hostent *
643gethostbyaddr(const char *addr, int len, int af)
644{
645 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
646 const u_char *uaddr = (const u_char *)addr;
647 int n, size, i;
648 querybuf *buf;
649 struct hostent *hp;
650 char qbuf[MAXDNAME+1], *qp, *ep;
651 char lookups[MAXDNSLUS];
652 struct hostent *res;
653 extern struct hostent *_gethtbyaddr(const char *, int, int);
654 extern struct hostent *_yp_gethtbyaddr(const char *);
655
656 if (_res_init(0) == -1) {
657 res = _gethtbyaddr(addr, len, af);
658 return (res);
659 }
660
661 if (af == AF_INET6 && len == IN6ADDRSZ &&
662 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
663 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
664 h_errno = HOST_NOT_FOUND;
665 return (NULL);
666 }
667 if (af == AF_INET6 && len == IN6ADDRSZ &&
668 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
669 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
670 /* Unmap. */
671 addr += IN6ADDRSZ - INADDRSZ;
672 uaddr += IN6ADDRSZ - INADDRSZ;
673 af = AF_INET;
674 len = INADDRSZ;
675 }
676 switch (af) {
677 case AF_INET:
678 size = INADDRSZ;
679 break;
680 case AF_INET6:
681 size = IN6ADDRSZ;
682 break;
683 default:
684 errno = EAFNOSUPPORT;
685 h_errno = NETDB_INTERNAL;
686 return (NULL);
687 }
688 if (size != len) {
689 errno = EINVAL;
690 h_errno = NETDB_INTERNAL;
691 return (NULL);
692 }
693 ep = qbuf + sizeof(qbuf);
694 switch (af) {
695 case AF_INET:
696 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
697 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
698 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
699 break;
700 case AF_INET6:
701 qp = qbuf;
702 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
703 i = snprintf(qp, ep - qp, "%x.%x.",
704 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
705 if (i <= 0) {
706 errno = EINVAL;
707 h_errno = NETDB_INTERNAL;
708 return (NULL);
709 }
710 qp += i;
711 }
712 strlcpy(qp, "ip6.arpa", ep - qp);
713 break;
714 }
715
716 bcopy(_resp->lookups, lookups, sizeof lookups);
717 if (lookups[0] == '\0')
718 strlcpy(lookups, "bf", sizeof lookups);
719
720 hp = (struct hostent *)NULL;
721 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
722 switch (lookups[i]) {
723#ifdef YP
724 case 'y':
725 /* YP only supports AF_INET. */
726 if (af == AF_INET)
727 hp = _yp_gethtbyaddr(addr);
728 break;
729#endif
730 case 'b':
731 buf = malloc(sizeof(*buf));
732 if (!buf)
733 break;
734 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
735 sizeof(buf->buf));
736 if (n < 0) {
737 free(buf);
738#ifdef DEBUG
739 if (_resp->options & RES_DEBUG)
740 printf("res_query failed\n");
741#endif
742 break;
743 }
744 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
745 free(buf);
746 break;
747 }
748 free(buf);
749 hp->h_addrtype = af;
750 hp->h_length = len;
751 bcopy(addr, host_addr, len);
752 h_addr_ptrs[0] = (char *)host_addr;
753 h_addr_ptrs[1] = NULL;
754 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
755 map_v4v6_address((char*)host_addr,
756 (char*)host_addr);
757 hp->h_addrtype = AF_INET6;
758 hp->h_length = IN6ADDRSZ;
759 }
760 h_errno = NETDB_SUCCESS;
761 break;
762 case 'f':
763 hp = _gethtbyaddr(addr, len, af);
764 break;
765 }
766 }
767 /* XXX h_errno not correct in all cases... */
768 return (hp);
769}
770
771void
772_sethtent(int f)
773{
774 if (hostf == NULL)
775 hostf = fopen(_PATH_HOSTS, "r" );
776 else
777 rewind(hostf);
778 stayopen = f;
779}
780
781void
782_endhtent(void)
783{
784 if (hostf && !stayopen) {
785 (void) fclose(hostf);
786 hostf = NULL;
787 }
788}
789
790struct hostent *
791_gethtent(void)
792{
793 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
794 char *p, *cp, **q;
795 int af;
796 size_t len;
797
798 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
799 h_errno = NETDB_INTERNAL;
800 return (NULL);
801 }
802 again:
803 if ((p = fgetln(hostf, &len)) == NULL) {
804 h_errno = HOST_NOT_FOUND;
805 return (NULL);
806 }
807 if (p[len-1] == '\n')
808 len--;
809 if (len >= sizeof(hostbuf) || len == 0)
810 goto again;
811 p = memcpy(hostbuf, p, len);
812 hostbuf[len] = '\0';
813 if (*p == '#')
814 goto again;
815 if ((cp = strchr(p, '#')))
816 *cp = '\0';
817 if (!(cp = strpbrk(p, " \t")))
818 goto again;
819 *cp++ = '\0';
820 if (inet_pton(AF_INET6, p, host_addr) > 0) {
821 af = AF_INET6;
822 len = IN6ADDRSZ;
823 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
824 if (_resp->options & RES_USE_INET6) {
825 map_v4v6_address((char*)host_addr, (char*)host_addr);
826 af = AF_INET6;
827 len = IN6ADDRSZ;
828 } else {
829 af = AF_INET;
830 len = INADDRSZ;
831 }
832 } else {
833 goto again;
834 }
835 /* if this is not something we're looking for, skip it. */
836 if (host.h_addrtype != af)
837 goto again;
838 if (host.h_length != len)
839 goto again;
840 h_addr_ptrs[0] = (char *)host_addr;
841 h_addr_ptrs[1] = NULL;
842 host.h_addr_list = h_addr_ptrs;
843 host.h_length = len;
844 host.h_addrtype = af;
845 while (*cp == ' ' || *cp == '\t')
846 cp++;
847 host.h_name = cp;
848 q = host.h_aliases = host_aliases;
849 if ((cp = strpbrk(cp, " \t")))
850 *cp++ = '\0';
851 while (cp && *cp) {
852 if (*cp == ' ' || *cp == '\t') {
853 cp++;
854 continue;
855 }
856 if (q < &host_aliases[MAXALIASES - 1])
857 *q++ = cp;
858 if ((cp = strpbrk(cp, " \t")))
859 *cp++ = '\0';
860 }
861 *q = NULL;
862 if (_resp->options & RES_USE_INET6) {
863 char *bp = hostbuf;
864 char *ep = hostbuf + sizeof hostbuf;
865
866 map_v4v6_hostent(&host, &bp, ep);
867 }
868 h_errno = NETDB_SUCCESS;
869 return (&host);
870}
871
872struct hostent *
873_gethtbyname(const char *name)
874{
875 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
876 struct hostent *hp;
877 extern struct hostent *_gethtbyname2(const char *, int);
878
879 if (_resp->options & RES_USE_INET6) {
880 hp = _gethtbyname2(name, AF_INET6);
881 if (hp)
882 return (hp);
883 }
884 return (_gethtbyname2(name, AF_INET));
885}
886
887struct hostent *
888_gethtbyname2(const char *name, int af)
889{
890 struct hostent *p;
891 char **cp;
892
893 _sethtent(0);
894 while ((p = _gethtent())) {
895 if (p->h_addrtype != af)
896 continue;
897 if (strcasecmp(p->h_name, name) == 0)
898 break;
899 for (cp = p->h_aliases; *cp != 0; cp++)
900 if (strcasecmp(*cp, name) == 0)
901 goto found;
902 }
903 found:
904 _endhtent();
905 return (p);
906}
907
908struct hostent *
909_gethtbyaddr(const char *addr, int len, int af)
910{
911 struct hostent *p;
912
913 host.h_length = len;
914 host.h_addrtype = af;
915
916 _sethtent(0);
917 while ((p = _gethtent()))
918 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
919 break;
920 _endhtent();
921 return (p);
922}
923
924#ifdef YP
925struct hostent *
926_yphostent(char *line)
927{
928 static struct in_addr host_addrs[MAXADDRS];
929 char *p = line;
930 char *cp, **q;
931 char **hap;
932 struct in_addr *buf;
933 int more;
934
935 host.h_name = NULL;
936 host.h_addr_list = h_addr_ptrs;
937 host.h_length = INADDRSZ;
938 host.h_addrtype = AF_INET;
939 hap = h_addr_ptrs;
940 buf = host_addrs;
941 q = host.h_aliases = host_aliases;
942
943nextline:
944 /* check for host_addrs overflow */
945 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
946 goto done;
947
948 more = 0;
949 cp = strpbrk(p, " \t");
950 if (cp == NULL)
951 goto done;
952 *cp++ = '\0';
953
954 *hap++ = (char *)buf;
955 (void) inet_aton(p, buf++);
956
957 while (*cp == ' ' || *cp == '\t')
958 cp++;
959 p = cp;
960 cp = strpbrk(p, " \t\n");
961 if (cp != NULL) {
962 if (*cp == '\n')
963 more = 1;
964 *cp++ = '\0';
965 }
966 if (!host.h_name)
967 host.h_name = p;
968 else if (strcmp(host.h_name, p)==0)
969 ;
970 else if (q < &host_aliases[MAXALIASES - 1])
971 *q++ = p;
972 p = cp;
973 if (more)
974 goto nextline;
975
976 while (cp && *cp) {
977 if (*cp == ' ' || *cp == '\t') {
978 cp++;
979 continue;
980 }
981 if (*cp == '\n') {
982 cp++;
983 goto nextline;
984 }
985 if (q < &host_aliases[MAXALIASES - 1])
986 *q++ = cp;
987 cp = strpbrk(cp, " \t");
988 if (cp != NULL)
989 *cp++ = '\0';
990 }
991done:
992 if (host.h_name == NULL)
993 return (NULL);
994 *q = NULL;
995 *hap = NULL;
996 return (&host);
997}
998
999struct hostent *
1000_yp_gethtbyaddr(const char *addr)
1001{
1002 struct hostent *hp = (struct hostent *)NULL;
1003 static char *__ypcurrent;
1004 int __ypcurrentlen, r;
1005 char name[sizeof("xxx.xxx.xxx.xxx")];
1006
1007 if (!__ypdomain) {
1008 if (_yp_check(&__ypdomain) == 0)
1009 return (hp);
1010 }
1011 snprintf(name, sizeof name, "%u.%u.%u.%u",
1012 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
1013 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
1014 if (__ypcurrent)
1015 free(__ypcurrent);
1016 __ypcurrent = NULL;
1017 r = yp_match(__ypdomain, "hosts.byaddr", name,
1018 strlen(name), &__ypcurrent, &__ypcurrentlen);
1019 if (r==0)
1020 hp = _yphostent(__ypcurrent);
1021 if (hp==NULL)
1022 h_errno = HOST_NOT_FOUND;
1023 return (hp);
1024}
1025
1026struct hostent *
1027_yp_gethtbyname(const char *name)
1028{
1029 struct hostent *hp = (struct hostent *)NULL;
1030 static char *__ypcurrent;
1031 int __ypcurrentlen, r;
1032
1033 if (strlen(name) >= MAXHOSTNAMELEN)
1034 return (NULL);
1035 if (!__ypdomain) {
1036 if (_yp_check(&__ypdomain) == 0)
1037 return (hp);
1038 }
1039 if (__ypcurrent)
1040 free(__ypcurrent);
1041 __ypcurrent = NULL;
1042 r = yp_match(__ypdomain, "hosts.byname", name,
1043 strlen(name), &__ypcurrent, &__ypcurrentlen);
1044 if (r == 0)
1045 hp = _yphostent(__ypcurrent);
1046 if (hp == NULL)
1047 h_errno = HOST_NOT_FOUND;
1048 return (hp);
1049}
1050#endif
1051
1052static void
1053map_v4v6_address(const char *src, char *dst)
1054{
1055 u_char *p = (u_char *)dst;
1056 char tmp[INADDRSZ];
1057 int i;
1058
1059 /* Stash a temporary copy so our caller can update in place. */
1060 bcopy(src, tmp, INADDRSZ);
1061 /* Mark this ipv6 addr as a mapped ipv4. */
1062 for (i = 0; i < 10; i++)
1063 *p++ = 0x00;
1064 *p++ = 0xff;
1065 *p++ = 0xff;
1066 /* Retrieve the saved copy and we're done. */
1067 bcopy(tmp, (void*)p, INADDRSZ);
1068}
1069
1070static void
1071map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1072{
1073 char **ap;
1074
1075 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1076 return;
1077 hp->h_addrtype = AF_INET6;
1078 hp->h_length = IN6ADDRSZ;
1079 for (ap = hp->h_addr_list; *ap; ap++) {
1080 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1081
1082 if (ep - *bpp < (i + IN6ADDRSZ)) {
1083 /* Out of memory. Truncate address list here. XXX */
1084 *ap = NULL;
1085 return;
1086 }
1087 *bpp += i;
1088 map_v4v6_address(*ap, *bpp);
1089 *ap = *bpp;
1090 *bpp += IN6ADDRSZ;
1091 }
1092}
1093
1094struct hostent *
1095gethostent(void)
1096{
1097 return (_gethtent());
1098}
1099
1100#ifdef RESOLVSORT
1101static void
1102addrsort(char **ap, int num)
1103{
1104 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1105 int i, j;
1106 char **p;
1107 short aval[MAXADDRS];
1108 int needsort = 0;
1109
1110 p = ap;
1111 for (i = 0; i < num; i++, p++) {
1112 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1113 if (_resp->sort_list[j].addr.s_addr ==
1114 (((struct in_addr *)(*p))->s_addr &
1115 _resp->sort_list[j].mask))
1116 break;
1117 aval[i] = j;
1118 if (needsort == 0 && i > 0 && j < aval[i-1])
1119 needsort = i;
1120 }
1121 if (!needsort)
1122 return;
1123
1124 while (needsort < num) {
1125 for (j = needsort - 1; j >= 0; j--) {
1126 if (aval[j] > aval[j+1]) {
1127 char *hp;
1128
1129 i = aval[j];
1130 aval[j] = aval[j+1];
1131 aval[j+1] = i;
1132
1133 hp = ap[j];
1134 ap[j] = ap[j+1];
1135 ap[j+1] = hp;
1136 } else
1137 break;
1138 }
1139 needsort++;
1140 }
1141}
1142#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..ffbdf4da41
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,158 @@
1.\" $OpenBSD: getifaddrs.3,v 1.11 2004/04/16 10:48:39 jmc Exp $
2.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
3.\"
4.\" Copyright (c) 1995, 1999
5.\" Berkeley Software Design, Inc. 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.\"
13.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.Dd October 12, 1995
25.Dt GETIFADDRS 3
26.Os
27.Sh NAME
28.Nm getifaddrs
29.Nd get interface addresses
30.Sh SYNOPSIS
31.Fd #include <sys/types.h>
32.Fd #include <sys/socket.h>
33.Fd #include <ifaddrs.h>
34.Ft int
35.Fn getifaddrs "struct ifaddrs **ifap"
36.Ft void
37.Fn freeifaddrs "struct ifaddrs *ifap"
38.Sh DESCRIPTION
39The
40.Fn getifaddrs
41function stores a reference to a linked list of the network interfaces
42on the local machine in the memory referenced by
43.Fa ifap .
44The list consists of
45.Nm ifaddrs
46structures, as defined in the include file
47.Aq Pa ifaddrs.h .
48The
49.Nm ifaddrs
50structure contains at least the following entries:
51.Bd -literal
52 struct ifaddrs *ifa_next; /* Pointer to next struct */
53 char *ifa_name; /* Interface name */
54 u_int ifa_flags; /* Interface flags */
55 struct sockaddr *ifa_addr; /* Interface address */
56 struct sockaddr *ifa_netmask; /* Interface netmask */
57 struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
58 struct sockaddr *ifa_dstaddr; /* P2P interface destination */
59 void *ifa_data; /* Address specific data */
60.Ed
61.Bl -tag -width Ds
62.It Fa ifa_next
63Contains a pointer to the next structure on the list.
64This field is set to
65.Dv NULL
66in last structure on the list.
67.It Fa ifa_name
68Contains the interface name.
69.It Fa ifa_flags
70Contains the interface flags, as set by
71.Xr ifconfig 8 .
72.It Fa ifa_addr
73References either the address of the interface or the link level
74address of the interface, if one exists, otherwise it is
75.Dv NULL .
76(The
77.Fa sa_family
78field of the
79.Fa ifa_addr
80field should be consulted to determine the format of the
81.Fa ifa_addr
82address.)
83.It Fa ifa_netmask
84References the netmask associated with
85.Fa ifa_addr ,
86if one is set, otherwise it is
87.Dv NULL .
88.It Fa ifa_broadaddr
89This field, which should only be referenced for non-P2P interfaces,
90references the broadcast address associated with
91.Fa ifa_addr ,
92if one exists, otherwise it is
93.Dv NULL .
94.It Fa ifa_dstaddr
95References the destination address on a P2P interface,
96if one exists, otherwise it is
97.Dv NULL .
98.It Fa ifa_data
99References address family specific data.
100For
101.Dv AF_LINK
102addresses it contains a pointer to the
103.Li struct if_data
104(as defined in include file
105.Aq Pa net/if.h )
106which contains various interface attributes and statistics.
107For all other address families, it contains a pointer to the
108.Li struct ifa_data
109(as defined in include file
110.Aq Pa net/if.h )
111which contains per-address interface statistics.
112.El
113.Pp
114The data returned by
115.Fn getifaddrs
116is dynamically allocated and should be freed using
117.Fn freeifaddrs
118when no longer needed.
119.Sh RETURN VALUES
120Upon successful completion, a value of 0 is returned.
121Otherwise, a value of \-1 is returned and
122.Va errno
123is set to indicate the error.
124.Sh ERRORS
125The
126.Fn getifaddrs
127may fail and set
128.Va errno
129for any of the errors specified for the library routines
130.Xr ioctl 2 ,
131.Xr socket 2 ,
132.Xr malloc 3 ,
133or
134.Xr sysctl 3 .
135.Sh SEE ALSO
136.Xr ioctl 2 ,
137.Xr socket 2 ,
138.Xr sysctl 3 ,
139.Xr networking 4 ,
140.Xr ifconfig 8
141.Sh HISTORY
142The
143.Fn getifaddrs
144function first appeared in BSDI BSD/OS.
145The function is supplied on
146.Ox
147since
148.Ox 2.7 .
149.Sh BUGS
150If both
151.Aq Pa net/if.h
152and
153.Aq Pa ifaddrs.h
154are being included,
155.Aq Pa net/if.h
156.Em must
157be included before
158.Aq Pa ifaddrs.h .
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
new file mode 100644
index 0000000000..0db89f6c19
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.c
@@ -0,0 +1,277 @@
1/* $OpenBSD: getifaddrs.c,v 1.9 2002/08/09 06:12:25 itojun Exp $ */
2
3/*
4 * Copyright (c) 1995, 1999
5 * Berkeley Software Design, Inc. 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 *
13 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 */
27
28#include <sys/types.h>
29#include <sys/ioctl.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <sys/param.h>
33#include <net/route.h>
34#include <sys/sysctl.h>
35#include <net/if_dl.h>
36
37#include <errno.h>
38#include <ifaddrs.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#define SALIGN (sizeof(long) - 1)
44#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
45
46int
47getifaddrs(struct ifaddrs **pif)
48{
49 int icnt = 1;
50 int dcnt = 0;
51 int ncnt = 0;
52 int mib[6];
53 size_t needed;
54 char *buf;
55 char *next;
56 struct ifaddrs *cif = 0;
57 char *p, *p0;
58 struct rt_msghdr *rtm;
59 struct if_msghdr *ifm;
60 struct ifa_msghdr *ifam;
61 struct sockaddr_dl *dl;
62 struct sockaddr *sa;
63 u_short index = 0;
64 size_t len, alen;
65 struct ifaddrs *ifa, *ift;
66 int i;
67 char *data;
68 char *names;
69
70 mib[0] = CTL_NET;
71 mib[1] = PF_ROUTE;
72 mib[2] = 0; /* protocol */
73 mib[3] = 0; /* wildcard address family */
74 mib[4] = NET_RT_IFLIST;
75 mib[5] = 0; /* no flags */
76 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
77 return (-1);
78 if ((buf = malloc(needed)) == NULL)
79 return (-1);
80 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
81 free(buf);
82 return (-1);
83 }
84
85 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
86 rtm = (struct rt_msghdr *)next;
87 if (rtm->rtm_version != RTM_VERSION)
88 continue;
89 switch (rtm->rtm_type) {
90 case RTM_IFINFO:
91 ifm = (struct if_msghdr *)rtm;
92 if (ifm->ifm_addrs & RTA_IFP) {
93 index = ifm->ifm_index;
94 ++icnt;
95 dl = (struct sockaddr_dl *)(ifm + 1);
96 dcnt += SA_RLEN((struct sockaddr *)dl) +
97 ALIGNBYTES;
98 dcnt += sizeof(ifm->ifm_data);
99 ncnt += dl->sdl_nlen + 1;
100 } else
101 index = 0;
102 break;
103
104 case RTM_NEWADDR:
105 ifam = (struct ifa_msghdr *)rtm;
106 if (index && ifam->ifam_index != index)
107 abort(); /* XXX abort illegal in library */
108
109#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
110 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
111 break;
112 p = (char *)(ifam + 1);
113 ++icnt;
114 /* Scan to look for length of address */
115 alen = 0;
116 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
117 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
118 == 0)
119 continue;
120 sa = (struct sockaddr *)p;
121 len = SA_RLEN(sa);
122 if (i == RTAX_IFA) {
123 alen = len;
124 break;
125 }
126 p += len;
127 }
128 for (p = p0, i = 0; i < RTAX_MAX; i++) {
129 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
130 == 0)
131 continue;
132 sa = (struct sockaddr *)p;
133 len = SA_RLEN(sa);
134 if (i == RTAX_NETMASK && sa->sa_len == 0)
135 dcnt += alen;
136 else
137 dcnt += len;
138 p += len;
139 }
140 break;
141 }
142 }
143
144 if (icnt + dcnt + ncnt == 1) {
145 *pif = NULL;
146 free(buf);
147 return (0);
148 }
149 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
150 if (data == NULL) {
151 free(buf);
152 return(-1);
153 }
154
155 ifa = (struct ifaddrs *)data;
156 data += sizeof(struct ifaddrs) * icnt;
157 names = data + dcnt;
158
159 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
160 ift = ifa;
161
162 index = 0;
163 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
164 rtm = (struct rt_msghdr *)next;
165 if (rtm->rtm_version != RTM_VERSION)
166 continue;
167 switch (rtm->rtm_type) {
168 case RTM_IFINFO:
169 ifm = (struct if_msghdr *)rtm;
170 if (ifm->ifm_addrs & RTA_IFP) {
171 index = ifm->ifm_index;
172 dl = (struct sockaddr_dl *)(ifm + 1);
173
174 cif = ift;
175 ift->ifa_name = names;
176 ift->ifa_flags = (int)ifm->ifm_flags;
177 memcpy(names, dl->sdl_data, dl->sdl_nlen);
178 names[dl->sdl_nlen] = 0;
179 names += dl->sdl_nlen + 1;
180
181 ift->ifa_addr = (struct sockaddr *)data;
182 memcpy(data, dl,
183 ((struct sockaddr *)dl)->sa_len);
184 data += SA_RLEN((struct sockaddr *)dl);
185
186 /* ifm_data needs to be aligned */
187 ift->ifa_data = data = (void *)ALIGN(data);
188 memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
189 data += sizeof(ifm->ifm_data);
190
191 ift = (ift->ifa_next = ift + 1);
192 } else
193 index = 0;
194 break;
195
196 case RTM_NEWADDR:
197 ifam = (struct ifa_msghdr *)rtm;
198 if (index && ifam->ifam_index != index)
199 abort(); /* XXX abort illegal in library */
200
201 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
202 break;
203 ift->ifa_name = cif->ifa_name;
204 ift->ifa_flags = cif->ifa_flags;
205 ift->ifa_data = NULL;
206 p = (char *)(ifam + 1);
207 /* Scan to look for length of address */
208 alen = 0;
209 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
210 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
211 == 0)
212 continue;
213 sa = (struct sockaddr *)p;
214 len = SA_RLEN(sa);
215 if (i == RTAX_IFA) {
216 alen = len;
217 break;
218 }
219 p += len;
220 }
221 for (p = p0, i = 0; i < RTAX_MAX; i++) {
222 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
223 == 0)
224 continue;
225 sa = (struct sockaddr *)p;
226 len = SA_RLEN(sa);
227 switch (i) {
228 case RTAX_IFA:
229 ift->ifa_addr = (struct sockaddr *)data;
230 memcpy(data, p, len);
231 data += len;
232 break;
233
234 case RTAX_NETMASK:
235 ift->ifa_netmask =
236 (struct sockaddr *)data;
237 if (sa->sa_len == 0) {
238 memset(data, 0, alen);
239 data += alen;
240 break;
241 }
242 memcpy(data, p, len);
243 data += len;
244 break;
245
246 case RTAX_BRD:
247 ift->ifa_broadaddr =
248 (struct sockaddr *)data;
249 memcpy(data, p, len);
250 data += len;
251 break;
252 }
253 p += len;
254 }
255
256
257 ift = (ift->ifa_next = ift + 1);
258 break;
259 }
260 }
261
262 free(buf);
263 if (--ift >= ifa) {
264 ift->ifa_next = NULL;
265 *pif = ifa;
266 } else {
267 *pif = NULL;
268 free(ifa);
269 }
270 return (0);
271}
272
273void
274freeifaddrs(struct ifaddrs *ifp)
275{
276 free(ifp);
277}
diff --git a/src/lib/libc/net/getnameinfo.3 b/src/lib/libc/net/getnameinfo.3
new file mode 100644
index 0000000000..b17f2e4aeb
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,270 @@
1.\" $OpenBSD: getnameinfo.3,v 1.38 2005/01/29 00:49:47 jmc Exp $
2.\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
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 ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GETNAMEINFO 3
21.Os
22.Sh NAME
23.Nm getnameinfo
24.Nd socket address structure to hostname and service name
25.Sh SYNOPSIS
26.Fd #include <sys/types.h>
27.Fd #include <sys/socket.h>
28.Fd #include <netdb.h>
29.Ft int
30.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" "char *host" \
31 "size_t hostlen" "char *serv" "size_t servlen" "int flags"
32.Sh DESCRIPTION
33The
34.Fn getnameinfo
35function is used to convert a
36.Li sockaddr
37structure to a pair of host name and service strings.
38It is a replacement for and provides more flexibility than the
39.Xr gethostbyaddr 3
40and
41.Xr getservbyport 3
42functions and is the converse of the
43.Xr getaddrinfo 3
44function.
45.Pp
46The
47.Li sockaddr
48structure
49.Fa sa
50should point to either a
51.Li sockaddr_in
52or
53.Li sockaddr_in6
54structure (for IPv4 or IPv6 respectively) that is
55.Fa salen
56bytes long.
57.Pp
58The host and service names associated with
59.Fa sa
60are stored in
61.Fa host
62and
63.Fa serv
64which have length parameters
65.Fa hostlen
66and
67.Fa servlen .
68The maximum value for
69.Fa hostlen
70is
71.Dv NI_MAXHOST
72and
73the maximum value for
74.Fa servlen
75is
76.Dv NI_MAXSERV ,
77as defined by
78.Aq Pa netdb.h .
79If a length parameter is zero, no string will be stored.
80Otherwise, enough space must be provided to store the
81host name or service string plus a byte for the NUL terminator.
82.Pp
83The
84.Fa flags
85argument is formed by
86.Tn OR Ns 'ing
87the following values:
88.Bl -tag -width "NI_NUMERICHOSTXX"
89.It Dv NI_NOFQDN
90A fully qualified domain name is not required for local hosts.
91The local part of the fully qualified domain name is returned instead.
92.It Dv NI_NUMERICHOST
93Return the address in numeric form, as if calling
94.Xr inet_ntop 3 ,
95instead of a host name.
96.It Dv NI_NAMEREQD
97A name is required.
98If the host name cannot be found in DNS and this flag is set,
99a non-zero error code is returned.
100If the host name is not found and the flag is not set, the
101address is returned in numeric form.
102.It NI_NUMERICSERV
103The service name is returned as a digit string representing the port number.
104.It NI_DGRAM
105Specifies that the service being looked up is a datagram
106service, and causes
107.Xr getservbyport 3
108to be called with a second argument of
109.Dq udp
110instead of its default of
111.Dq tcp .
112This is required for the few ports (512\-514) that have different services
113for
114.Tn UDP
115and
116.Tn TCP .
117.El
118.Pp
119This implementation allows numeric IPv6 address notation with scope identifier,
120as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
121IPv6 link-local address will appear as a string like
122.Dq Li fe80::1%ne0 .
123Refer to
124.Xr getaddrinfo 3
125for more information.
126.Sh RETURN VALUES
127.Fn getnameinfo
128returns zero on success or one of the error codes listed in
129.Xr gai_strerror 3
130if an error occurs.
131.Sh EXAMPLES
132The following code tries to get a numeric host name, and service name,
133for a given socket address.
134Observe that there is no hardcoded reference to a particular address family.
135.Bd -literal -offset indent
136struct sockaddr *sa; /* input */
137char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
138
139if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
140 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
141 errx(1, "could not get numeric hostname");
142 /*NOTREACHED*/
143}
144printf("host=%s, serv=%s\en", hbuf, sbuf);
145.Ed
146.Pp
147The following version checks if the socket address has a reverse address mapping:
148.Bd -literal -offset indent
149struct sockaddr *sa; /* input */
150char hbuf[NI_MAXHOST];
151
152if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
153 NI_NAMEREQD)) {
154 errx(1, "could not resolve hostname");
155 /*NOTREACHED*/
156}
157printf("host=%s\en", hbuf);
158.Ed
159.Sh SEE ALSO
160.Xr gai_strerror 3 ,
161.Xr getaddrinfo 3 ,
162.Xr gethostbyaddr 3 ,
163.Xr getservbyport 3 ,
164.Xr inet_ntop 3 ,
165.Xr resolver 3 ,
166.Xr hosts 5 ,
167.Xr resolv.conf 5 ,
168.Xr services 5 ,
169.Xr hostname 7 ,
170.Xr named 8
171.Rs
172.%A R. Gilligan
173.%A S. Thomson
174.%A J. Bound
175.%A W. Stevens
176.%T Basic Socket Interface Extensions for IPv6
177.%R RFC 2553
178.%D March 1999
179.Re
180.Rs
181.%A S. Deering
182.%A B. Haberman
183.%A T. Jinmei
184.%A E. Nordmark
185.%A B. Zill
186.%T "IPv6 Scoped Address Architecture"
187.%R internet draft
188.%N draft-ietf-ipv6-scoping-arch-02.txt
189.%O work in progress material
190.Re
191.Rs
192.%A Craig Metz
193.%T Protocol Independence Using the Sockets API
194.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
195.%D June 2000
196.Re
197.Sh STANDARDS
198The
199.Fn getnameinfo
200function is defined by the
201.St -p1003.1g-2000
202draft specification and documented in
203.Tn "RFC 2553" ,
204.Dq Basic Socket Interface Extensions for IPv6 .
205.Sh CAVEATS
206.Fn getnameinfo
207can return both numeric and FQDN forms of the address specified in
208.Fa sa .
209There is no return value that indicates whether the string returned in
210.Fa host
211is a result of binary to numeric-text translation (like
212.Xr inet_ntop 3 ) ,
213or is the result of a DNS reverse lookup.
214Because of this, malicious parties could set up a PTR record as follows:
215.Bd -literal -offset indent
2161.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
217.Ed
218.Pp
219and trick the caller of
220.Fn getnameinfo
221into believing that
222.Fa sa
223is
224.Li 10.1.1.1
225when it is actually
226.Li 127.0.0.1 .
227.Pp
228To prevent such attacks, the use of
229.Dv NI_NAMEREQD
230is recommended when the result of
231.Fn getnameinfo
232is used
233for access control purposes:
234.Bd -literal -offset indent
235struct sockaddr *sa;
236socklen_t salen;
237char addr[NI_MAXHOST];
238struct addrinfo hints, *res;
239int error;
240
241error = getnameinfo(sa, salen, addr, sizeof(addr),
242 NULL, 0, NI_NAMEREQD);
243if (error == 0) {
244 memset(&hints, 0, sizeof(hints));
245 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
246 hints.ai_flags = AI_NUMERICHOST;
247 if (getaddrinfo(addr, "0", &hints, &res) == 0) {
248 /* malicious PTR record */
249 freeaddrinfo(res);
250 printf("bogus PTR record\en");
251 return -1;
252 }
253 /* addr is FQDN as a result of PTR lookup */
254} else {
255 /* addr is numeric string */
256 error = getnameinfo(sa, salen, addr, sizeof(addr),
257 NULL, 0, NI_NUMERICHOST);
258}
259.Ed
260.Sh BUGS
261The implementation of
262.Fn getnameinfo
263is not thread-safe.
264.Pp
265.Ox
266intentionally uses a different
267.Dv NI_MAXHOST
268value from what
269.Tn "RFC 2553"
270suggests, to avoid buffer length handling mistakes.
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c
new file mode 100644
index 0000000000..830a94279e
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,356 @@
1/* $OpenBSD: getnameinfo.c,v 1.30 2005/03/25 13:24:12 otto Exp $ */
2/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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. Neither the name of the project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked
36 * - RFC2553 says that we should raise error on short buffer. X/Open says
37 * we need to truncate the result. We obey RFC2553 (and X/Open should be
38 * modified). ipngwg rough consensus seems to follow RFC2553.
39 * - What is "local" in NI_FQDN?
40 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
41 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
42 * sin6_scope_id is filled - standardization status?
43 * XXX breaks backward compat for code that expects no scopeid.
44 * beware on merge.
45 */
46
47#ifndef INET6
48#define INET6
49#endif
50
51#include <sys/types.h>
52#include <sys/socket.h>
53#include <net/if.h>
54#include <netinet/in.h>
55#include <arpa/inet.h>
56#include <arpa/nameser.h>
57#include <netdb.h>
58#include <resolv.h>
59#include <string.h>
60#include <stddef.h>
61
62#include "thread_private.h"
63
64static const struct afd {
65 int a_af;
66 int a_addrlen;
67 int a_socklen;
68 int a_off;
69} afdl [] = {
70#ifdef INET6
71 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
72 offsetof(struct sockaddr_in6, sin6_addr)},
73#endif
74 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
75 offsetof(struct sockaddr_in, sin_addr)},
76 {0, 0, 0},
77};
78
79struct sockinet {
80 u_char si_len;
81 u_char si_family;
82 u_short si_port;
83};
84
85#ifdef INET6
86static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
87 size_t, int);
88static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
89#endif
90
91/*
92 * this mutex is also used by get_port in getaddrinfo.c
93 */
94void *__THREAD_NAME(serv_mutex);
95
96int
97getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
98 size_t hostlen, char *serv, size_t servlen, int flags)
99{
100 const struct afd *afd;
101 struct servent *sp;
102 struct hostent *hp;
103 u_short port;
104 int family, i;
105 const char *addr;
106 u_int32_t v4a;
107 char numserv[512];
108 char numaddr[512];
109
110 if (sa == NULL)
111 return EAI_FAIL;
112
113 if (sa->sa_len != salen)
114 return EAI_FAIL;
115
116 family = sa->sa_family;
117 for (i = 0; afdl[i].a_af; i++)
118 if (afdl[i].a_af == family) {
119 afd = &afdl[i];
120 goto found;
121 }
122 return EAI_FAMILY;
123
124 found:
125 if (salen != afd->a_socklen)
126 return EAI_FAIL;
127
128 /* network byte order */
129 port = ((const struct sockinet *)sa)->si_port;
130 addr = (const char *)sa + afd->a_off;
131
132 if (serv == NULL || servlen == 0) {
133 /*
134 * do nothing in this case.
135 * in case you are wondering if "&&" is more correct than
136 * "||" here: rfc2553bis-03 says that serv == NULL OR
137 * servlen == 0 means that the caller does not want the result.
138 */
139 } else {
140 if (flags & NI_NUMERICSERV)
141 sp = NULL;
142 else {
143 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
144 sp = getservbyport(port,
145 (flags & NI_DGRAM) ? "udp" : "tcp");
146 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
147 }
148 if (sp) {
149 if (strlen(sp->s_name) + 1 > servlen)
150 return EAI_MEMORY;
151 strlcpy(serv, sp->s_name, servlen);
152 } else {
153 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
154 if (strlen(numserv) + 1 > servlen)
155 return EAI_MEMORY;
156 strlcpy(serv, numserv, servlen);
157 }
158 }
159
160 switch (sa->sa_family) {
161 case AF_INET:
162 v4a = (u_int32_t)
163 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
164 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
165 flags |= NI_NUMERICHOST;
166 v4a >>= IN_CLASSA_NSHIFT;
167 if (v4a == 0)
168 flags |= NI_NUMERICHOST;
169 break;
170#ifdef INET6
171 case AF_INET6:
172 {
173 const struct sockaddr_in6 *sin6;
174 sin6 = (const struct sockaddr_in6 *)sa;
175 switch (sin6->sin6_addr.s6_addr[0]) {
176 case 0x00:
177 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
178 ;
179 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
180 ;
181 else
182 flags |= NI_NUMERICHOST;
183 break;
184 default:
185 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
186 flags |= NI_NUMERICHOST;
187 }
188 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
189 flags |= NI_NUMERICHOST;
190 break;
191 }
192 }
193 break;
194#endif
195 }
196 if (host == NULL || hostlen == 0) {
197 /*
198 * do nothing in this case.
199 * in case you are wondering if "&&" is more correct than
200 * "||" here: rfc2553bis-03 says that host == NULL or
201 * hostlen == 0 means that the caller does not want the result.
202 */
203 } else if (flags & NI_NUMERICHOST) {
204 int numaddrlen;
205
206 /* NUMERICHOST and NAMEREQD conflicts with each other */
207 if (flags & NI_NAMEREQD)
208 return EAI_NONAME;
209
210 switch(afd->a_af) {
211#ifdef INET6
212 case AF_INET6:
213 {
214 int error;
215
216 if ((error = ip6_parsenumeric(sa, addr, host,
217 hostlen, flags)) != 0)
218 return(error);
219 break;
220 }
221#endif
222 default:
223 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
224 == NULL)
225 return EAI_SYSTEM;
226 numaddrlen = strlen(numaddr);
227 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
228 return EAI_MEMORY;
229 strlcpy(host, numaddr, hostlen);
230 break;
231 }
232 } else {
233 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
234 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
235 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
236
237 if (hp) {
238#if 0
239 /*
240 * commented out, since "for local host" is not
241 * implemented here - see RFC2553 p30
242 */
243 if (flags & NI_NOFQDN) {
244 char *p;
245 p = strchr(hp->h_name, '.');
246 if (p)
247 *p = '\0';
248 }
249#endif
250 if (strlen(hp->h_name) + 1 > hostlen) {
251 return EAI_MEMORY;
252 }
253 strlcpy(host, hp->h_name, hostlen);
254 } else {
255 if (flags & NI_NAMEREQD)
256 return EAI_NONAME;
257 switch(afd->a_af) {
258#ifdef INET6
259 case AF_INET6:
260 {
261 int error;
262
263 if ((error = ip6_parsenumeric(sa, addr, host,
264 hostlen,
265 flags)) != 0)
266 return(error);
267 break;
268 }
269#endif
270 default:
271 if (inet_ntop(afd->a_af, addr, host,
272 hostlen) == NULL)
273 return EAI_SYSTEM;
274 break;
275 }
276 }
277 }
278 return(0);
279}
280
281#ifdef INET6
282static int
283ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
284 size_t hostlen, int flags)
285{
286 int numaddrlen;
287 char numaddr[512];
288
289 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
290 return EAI_SYSTEM;
291
292 numaddrlen = strlen(numaddr);
293 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
294 return EAI_MEMORY;
295 strlcpy(host, numaddr, hostlen);
296
297 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
298 char zonebuf[MAXHOSTNAMELEN];
299 int zonelen;
300
301 zonelen = ip6_sa2str(
302 (const struct sockaddr_in6 *)(const void *)sa,
303 zonebuf, sizeof(zonebuf), flags);
304 if (zonelen < 0)
305 return EAI_MEMORY;
306 if (zonelen + 1 + numaddrlen + 1 > hostlen)
307 return EAI_MEMORY;
308
309 /* construct <numeric-addr><delim><zoneid> */
310 memcpy(host + numaddrlen + 1, zonebuf,
311 (size_t)zonelen);
312 host[numaddrlen] = SCOPE_DELIMITER;
313 host[numaddrlen + 1 + zonelen] = '\0';
314 }
315
316 return 0;
317}
318
319/* ARGSUSED */
320static int
321ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
322{
323 unsigned int ifindex;
324 const struct in6_addr *a6;
325 int n;
326
327 ifindex = (unsigned int)sa6->sin6_scope_id;
328 a6 = &sa6->sin6_addr;
329
330#ifdef notdef
331 if ((flags & NI_NUMERICSCOPE) != 0) {
332 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
333 if (n < 0 || n >= bufsiz)
334 return -1;
335 else
336 return n;
337 }
338#endif
339
340 /* if_indextoname() does not take buffer size. not a good api... */
341 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
342 bufsiz >= IF_NAMESIZE) {
343 char *p = if_indextoname(ifindex, buf);
344 if (p) {
345 return(strlen(p));
346 }
347 }
348
349 /* last resort */
350 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
351 if (n < 0 || n >= bufsiz)
352 return -1;
353 else
354 return n;
355}
356#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
new file mode 100644
index 0000000000..82d1ea1dca
--- /dev/null
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.7 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35
36extern int _net_stayopen;
37
38struct netent *
39_getnetbyaddr(in_addr_t net, int type)
40{
41 struct netent *p;
42
43 setnetent(_net_stayopen);
44 while ((p = getnetent()))
45 if (p->n_addrtype == type && p->n_net == net)
46 break;
47 if (!_net_stayopen)
48 endnetent();
49 return (p);
50}
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
new file mode 100644
index 0000000000..83b3ca3817
--- /dev/null
+++ b/src/lib/libc/net/getnetbyname.c
@@ -0,0 +1,57 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.7 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <string.h>
36
37extern int _net_stayopen;
38
39struct netent *
40_getnetbyname(const char *name)
41{
42 struct netent *p;
43 char **cp;
44
45 setnetent(_net_stayopen);
46 while ((p = getnetent())) {
47 if (strcasecmp(p->n_name, name) == 0)
48 break;
49 for (cp = p->n_aliases; *cp != 0; cp++)
50 if (strcasecmp(*cp, name) == 0)
51 goto found;
52 }
53found:
54 if (!_net_stayopen)
55 endnetent();
56 return (p);
57}
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
new file mode 100644
index 0000000000..40b50a8c3f
--- /dev/null
+++ b/src/lib/libc/net/getnetent.3
@@ -0,0 +1,140 @@
1.\" $OpenBSD: getnetent.3,v 1.13 2004/02/01 19:45:00 nordin Exp $
2.\"
3.\" Copyright (c) 1983, 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 March 13, 1997
31.Dt GETNETENT 3
32.Os
33.Sh NAME
34.Nm getnetent ,
35.Nm getnetbyaddr ,
36.Nm getnetbyname ,
37.Nm setnetent ,
38.Nm endnetent
39.Nd get network entry
40.Sh SYNOPSIS
41.Fd #include <netdb.h>
42.Ft struct netent *
43.Fn getnetent "void"
44.Ft struct netent *
45.Fn getnetbyname "const char *name"
46.Ft struct netent *
47.Fn getnetbyaddr "in_addr_t net" "int type"
48.Ft void
49.Fn setnetent "int stayopen"
50.Ft void
51.Fn endnetent "void"
52.Sh DESCRIPTION
53The
54.Fn getnetent ,
55.Fn getnetbyname ,
56and
57.Fn getnetbyaddr
58functions each return a pointer to an object with the following structure
59containing the broken-out fields of a line in the network database,
60.Pa /etc/networks .
61.Bd -literal -offset indent
62struct netent {
63 char *n_name; /* official name of net */
64 char **n_aliases; /* alias list */
65 int n_addrtype; /* net number type */
66 in_addr_t n_net; /* net number */
67};
68.Ed
69.Pp
70The members of this structure are:
71.Bl -tag -width n_addrtype
72.It Fa n_name
73The official name of the network.
74.It Fa n_aliases
75A zero-terminated list of alternate names for the network.
76.It Fa n_addrtype
77The type of the network number returned; currently only
78.Dv AF_INET .
79.It Fa n_net
80The network number.
81Network numbers are returned in machine byte order.
82.El
83.Pp
84The
85.Fn getnetent
86function reads the next line of the file, opening the file if necessary.
87.Pp
88The
89.Fn setnetent
90function opens and rewinds the file.
91If the
92.Fa stayopen
93flag is non-zero,
94the net database will not be closed after each call to
95.Fn getnetbyname
96or
97.Fn getnetbyaddr .
98.Pp
99The
100.Fn endnetent
101function closes the file.
102.Pp
103The
104.Fn getnetbyname
105and
106.Fn getnetbyaddr
107functions search the domain name server if the system is configured to use one.
108If the search fails, or no name server is configured, they sequentially
109search from the beginning of the file until a matching net name or
110net address and type is found, or until
111.Dv EOF
112is encountered.
113Network numbers are supplied in host order.
114.Sh FILES
115.Bl -tag -width /etc/networks -compact
116.It Pa /etc/networks
117.El
118.Sh DIAGNOSTICS
119Null pointer (0) returned on
120.Dv EOF
121or error.
122.Sh SEE ALSO
123.Xr resolver 3 ,
124.Xr networks 5
125.Sh HISTORY
126The
127.Fn getnetent ,
128.Fn getnetbyaddr ,
129.Fn getnetbyname ,
130.Fn setnetent ,
131and
132.Fn endnetent
133functions appeared in
134.Bx 4.2 .
135.Sh BUGS
136The data space used by these functions is static; if future use
137requires the data, it should be copied before any subsequent calls
138to these functions overwrite it.
139Only Internet network numbers are currently understood.
140Expecting network numbers to fit in no more than 32 bits is naive.
diff --git a/src/lib/libc/net/getnetent.c b/src/lib/libc/net/getnetent.c
new file mode 100644
index 0000000000..3e52c1ff4d
--- /dev/null
+++ b/src/lib/libc/net/getnetent.c
@@ -0,0 +1,124 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetent.c,v 1.10 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <netdb.h>
39#include <stdio.h>
40#include <string.h>
41
42#define MAXALIASES 35
43
44static FILE *netf;
45static char line[BUFSIZ+1];
46static struct netent net;
47static char *net_aliases[MAXALIASES];
48int _net_stayopen;
49
50void
51setnetent(int f)
52{
53 if (netf == NULL)
54 netf = fopen(_PATH_NETWORKS, "r" );
55 else
56 rewind(netf);
57 _net_stayopen |= f;
58}
59
60void
61endnetent(void)
62{
63 if (netf) {
64 fclose(netf);
65 netf = NULL;
66 }
67 _net_stayopen = 0;
68}
69
70struct netent *
71getnetent(void)
72{
73 char *p, *cp, **q;
74 size_t len;
75
76 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
77 return (NULL);
78again:
79 if ((p = fgetln(netf, &len)) == NULL)
80 return (NULL);
81 if (p[len-1] == '\n')
82 len--;
83 if (len >= sizeof(line) || len == 0)
84 goto again;
85 p = memcpy(line, p, len);
86 line[len] = '\0';
87 if (*p == '#')
88 goto again;
89 if ((cp = strchr(p, '#')) != NULL)
90 *cp = '\0';
91 net.n_name = p;
92 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
93 net.n_name[MAXHOSTNAMELEN-1] = '\0';
94 cp = strpbrk(p, " \t");
95 if (cp == NULL)
96 goto again;
97 *cp++ = '\0';
98 while (*cp == ' ' || *cp == '\t')
99 cp++;
100 p = strpbrk(cp, " \t");
101 if (p != NULL)
102 *p++ = '\0';
103 net.n_net = inet_network(cp);
104 net.n_addrtype = AF_INET;
105 q = net.n_aliases = net_aliases;
106 if (p != NULL)
107 cp = p;
108 while (cp && *cp) {
109 if (*cp == ' ' || *cp == '\t') {
110 cp++;
111 continue;
112 }
113 if (q < &net_aliases[MAXALIASES - 1]) {
114 *q++ = cp;
115 if (strlen(cp) >= MAXHOSTNAMELEN-1)
116 cp[MAXHOSTNAMELEN-1] = '\0';
117 }
118 cp = strpbrk(cp, " \t");
119 if (cp != NULL)
120 *cp++ = '\0';
121 }
122 *q = NULL;
123 return (&net);
124}
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..303ac2cc54
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,394 @@
1/* $OpenBSD: getnetnamadr.c,v 1.25 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * Copyright (c) 1997, Jason Downs. 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
28 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
29 *
30 * Permission to use, copy, modify, and distribute this software for any
31 * purpose with or without fee is hereby granted, provided that the above
32 * copyright notice and this permission notice appear in all copies.
33 */
34/*
35 * Copyright (c) 1983, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63#if defined(LIBC_SCCS) && !defined(lint)
64#if 0
65static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
66static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
67static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
68#else
69static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.25 2005/03/30 02:58:28 tedu Exp $";
70#endif
71#endif /* LIBC_SCCS and not lint */
72
73#include <sys/types.h>
74#include <sys/param.h>
75#include <sys/socket.h>
76#include <netinet/in.h>
77#include <arpa/inet.h>
78#include <arpa/nameser.h>
79
80#include <stdio.h>
81#include <netdb.h>
82#include <resolv.h>
83#include <ctype.h>
84#include <errno.h>
85#include <string.h>
86#include <stdlib.h>
87
88#include "thread_private.h"
89
90extern int h_errno;
91
92struct netent *_getnetbyaddr(in_addr_t net, int type);
93struct netent *_getnetbyname(const char *name);
94
95int _hokchar(const char *);
96
97#define BYADDR 0
98#define BYNAME 1
99#define MAXALIASES 35
100
101#define MAXPACKET (64*1024)
102
103typedef union {
104 HEADER hdr;
105 u_char buf[MAXPACKET];
106} querybuf;
107
108typedef union {
109 long al;
110 char ac;
111} align;
112
113static struct netent *
114getnetanswer(querybuf *answer, int anslen, int net_i)
115{
116
117 HEADER *hp;
118 u_char *cp;
119 int n;
120 u_char *eom;
121 int type, class, ancount, qdcount, haveanswer, i, nchar;
122 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
123 char *in, *st, *pauxt, *bp, **ap, *ep;
124 char *paux1 = &aux1[0], *paux2 = &aux2[0];
125 static struct netent net_entry;
126 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
127
128 /*
129 * find first satisfactory answer
130 *
131 * answer --> +------------+ ( MESSAGE )
132 * | Header |
133 * +------------+
134 * | Question | the question for the name server
135 * +------------+
136 * | Answer | RRs answering the question
137 * +------------+
138 * | Authority | RRs pointing toward an authority
139 * | Additional | RRs holding additional information
140 * +------------+
141 */
142 eom = answer->buf + anslen;
143 hp = &answer->hdr;
144 ancount = ntohs(hp->ancount); /* #/records in the answer section */
145 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
146 bp = netbuf;
147 ep = netbuf + sizeof(netbuf);
148 cp = answer->buf + HFIXEDSZ;
149 if (!qdcount) {
150 if (hp->aa)
151 h_errno = HOST_NOT_FOUND;
152 else
153 h_errno = TRY_AGAIN;
154 return (NULL);
155 }
156 while (qdcount-- > 0) {
157 n = __dn_skipname(cp, eom);
158 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
159 h_errno = NO_RECOVERY;
160 return(NULL);
161 }
162 cp += n + QFIXEDSZ;
163 }
164 ap = net_aliases;
165 *ap = NULL;
166 net_entry.n_aliases = net_aliases;
167 haveanswer = 0;
168 while (--ancount >= 0 && cp < eom) {
169 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
170#ifdef USE_RESOLV_NAME_OK
171 if ((n < 0) || !res_dnok(bp))
172#else
173 if ((n < 0) || !_hokchar(bp))
174#endif
175 break;
176 cp += n;
177 ans[0] = '\0';
178 strlcpy(&ans[0], bp, sizeof ans);
179 GETSHORT(type, cp);
180 GETSHORT(class, cp);
181 cp += INT32SZ; /* TTL */
182 GETSHORT(n, cp);
183 if (class == C_IN && type == T_PTR) {
184 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
185#ifdef USE_RESOLV_NAME_OK
186 if ((n < 0) || !res_hnok(bp))
187#else
188 if ((n < 0) || !_hokchar(bp))
189#endif
190 {
191 cp += n;
192 return (NULL);
193 }
194 cp += n;
195 if ((ap + 2) < &net_aliases[MAXALIASES]) {
196 *ap++ = bp;
197 bp += strlen(bp) + 1;
198 net_entry.n_addrtype =
199 (class == C_IN) ? AF_INET : AF_UNSPEC;
200 haveanswer++;
201 }
202 }
203 }
204 if (haveanswer) {
205 *ap = NULL;
206 switch (net_i) {
207 case BYADDR:
208 net_entry.n_name = *net_entry.n_aliases;
209 net_entry.n_net = 0L;
210 break;
211 case BYNAME:
212 ap = net_entry.n_aliases;
213 next_alias:
214 in = *ap++;
215 if (in == NULL) {
216 h_errno = HOST_NOT_FOUND;
217 return (NULL);
218 }
219 net_entry.n_name = ans;
220 aux2[0] = '\0';
221 for (i = 0; i < 4; i++) {
222 for (st = in, nchar = 0;
223 isdigit((unsigned char)*st);
224 st++, nchar++)
225 ;
226 if (*st != '.' || nchar == 0 || nchar > 3)
227 goto next_alias;
228 if (i != 0)
229 nchar++;
230 strlcpy(paux1, in, nchar+1);
231 strlcat(paux1, paux2, MAXHOSTNAMELEN);
232 pauxt = paux2;
233 paux2 = paux1;
234 paux1 = pauxt;
235 in = ++st;
236 }
237 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
238 goto next_alias;
239 net_entry.n_net = inet_network(paux2);
240 break;
241 }
242 net_entry.n_aliases++;
243 return (&net_entry);
244 }
245 h_errno = TRY_AGAIN;
246 return (NULL);
247}
248
249struct netent *
250getnetbyaddr(in_addr_t net, int net_type)
251{
252 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
253 unsigned int netbr[4];
254 int nn, anslen;
255 querybuf *buf;
256 char qbuf[MAXDNAME];
257 in_addr_t net2;
258 struct netent *net_entry = NULL;
259 char lookups[MAXDNSLUS];
260 int i;
261
262 if (_res_init(0) == -1)
263 return(_getnetbyaddr(net, net_type));
264
265 bcopy(_resp->lookups, lookups, sizeof lookups);
266 if (lookups[0] == '\0')
267 strlcpy(lookups, "bf", sizeof lookups);
268
269 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
270 switch (lookups[i]) {
271#ifdef YP
272 case 'y':
273 /* There is no YP support. */
274 break;
275#endif /* YP */
276 case 'b':
277 if (net_type != AF_INET)
278 break; /* DNS only supports AF_INET? */
279
280 for (nn = 4, net2 = net; net2; net2 >>= 8)
281 netbr[--nn] = net2 & 0xff;
282 switch (nn) {
283 case 3: /* Class A */
284 snprintf(qbuf, sizeof(qbuf),
285 "0.0.0.%u.in-addr.arpa", netbr[3]);
286 break;
287 case 2: /* Class B */
288 snprintf(qbuf, sizeof(qbuf),
289 "0.0.%u.%u.in-addr.arpa",
290 netbr[3], netbr[2]);
291 break;
292 case 1: /* Class C */
293 snprintf(qbuf, sizeof(qbuf),
294 "0.%u.%u.%u.in-addr.arpa",
295 netbr[3], netbr[2], netbr[1]);
296 break;
297 case 0: /* Class D - E */
298 snprintf(qbuf, sizeof(qbuf),
299 "%u.%u.%u.%u.in-addr.arpa",
300 netbr[3], netbr[2], netbr[1], netbr[0]);
301 break;
302 }
303 buf = malloc(sizeof(*buf));
304 if (buf == NULL)
305 break;
306 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
307 sizeof(buf->buf));
308 if (anslen < 0) {
309 free(buf);
310#ifdef DEBUG
311 if (_resp->options & RES_DEBUG)
312 printf("res_query failed\n");
313#endif
314 break;
315 }
316 net_entry = getnetanswer(buf, anslen, BYADDR);
317 free(buf);
318 if (net_entry != NULL) {
319 unsigned u_net = net; /* maybe net should be unsigned ? */
320
321 /* Strip trailing zeros */
322 while ((u_net & 0xff) == 0 && u_net != 0)
323 u_net >>= 8;
324 net_entry->n_net = u_net;
325 return (net_entry);
326 }
327 break;
328 case 'f':
329 net_entry = _getnetbyaddr(net, net_type);
330 if (net_entry != NULL)
331 return (net_entry);
332 }
333 }
334
335 /* Nothing matched. */
336 return (NULL);
337}
338
339struct netent *
340getnetbyname(const char *net)
341{
342 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
343 int anslen;
344 querybuf *buf;
345 char qbuf[MAXDNAME];
346 struct netent *net_entry = NULL;
347 char lookups[MAXDNSLUS];
348 int i;
349
350 if (_res_init(0) == -1)
351 return (_getnetbyname(net));
352
353 bcopy(_resp->lookups, lookups, sizeof lookups);
354 if (lookups[0] == '\0')
355 strlcpy(lookups, "bf", sizeof lookups);
356
357 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
358 switch (lookups[i]) {
359#ifdef YP
360 case 'y':
361 /* There is no YP support. */
362 break;
363#endif /* YP */
364 case 'b':
365 strlcpy(qbuf, net, sizeof qbuf);
366 buf = malloc(sizeof(*buf));
367 if (buf == NULL)
368 break;
369 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
370 sizeof(buf->buf));
371 if (anslen < 0) {
372 free(buf);
373#ifdef DEBUG
374 if (_resp->options & RES_DEBUG)
375 printf("res_query failed\n");
376#endif
377 break;
378 }
379 net_entry = getnetanswer(buf, anslen, BYNAME);
380 free(buf);
381 if (net_entry != NULL)
382 return (net_entry);
383 break;
384 case 'f':
385 net_entry = _getnetbyname(net);
386 if (net_entry != NULL)
387 return (net_entry);
388 break;
389 }
390 }
391
392 /* Nothing matched. */
393 return (NULL);
394}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
new file mode 100644
index 0000000000..16d840394c
--- /dev/null
+++ b/src/lib/libc/net/getproto.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getproto.c,v 1.6 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <stdio.h>
36
37int
38getprotobynumber_r(int num, struct protoent *pe, struct protoent_data *pd)
39{
40 int error;
41
42 setprotoent_r(pd->stayopen, pd);
43 while ((error = getprotoent_r(pe, pd)) == 0)
44 if (pe->p_proto == num)
45 break;
46 if (!pd->stayopen && pd->fp != NULL) {
47 (void)fclose(pd->fp);
48 pd->fp = NULL;
49 }
50 return (error);
51}
52
53struct protoent *
54getprotobynumber(int num)
55{
56 extern struct protoent_data _protoent_data;
57 static struct protoent proto;
58
59 if (getprotobynumber_r(num, &proto, &_protoent_data) != 0)
60 return (NULL);
61 return (&proto);
62}
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
new file mode 100644
index 0000000000..ea2a9e7777
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.3
@@ -0,0 +1,213 @@
1.\" $OpenBSD: getprotoent.3,v 1.14 2005/02/19 21:35:42 millert Exp $
2.\"
3.\" Copyright (c) 1983, 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 October 13, 2004
31.Dt GETPROTOENT 3
32.Os
33.Sh NAME
34.Nm getprotoent ,
35.Nm getprotoent_r ,
36.Nm getprotobynumber ,
37.Nm getprotobynumber_r ,
38.Nm getprotobyname ,
39.Nm getprotobyname_r ,
40.Nm setprotoent ,
41.Nm setprotoent_r ,
42.Nm endprotoent ,
43.Nm endprotoent_r
44.Nd get protocol entry
45.Sh SYNOPSIS
46.Fd #include <netdb.h>
47.Ft struct protoent *
48.Fn getprotoent "void"
49.Ft int
50.Fn getprotoent_r "struct protoent *protoent" "struct protoent_data *protoent_data"
51.Ft struct protoent *
52.Fn getprotobyname "const char *name"
53.Ft int
54.Fn getprotobyname_r "const char *name" "struct protoent *protoent" "struct protoent_data *protoent_data"
55.Ft struct protoent *
56.Fn getprotobynumber "int proto"
57.Ft int
58.Fn getprotobynumber_r "int proto" "struct protoent *protoent" "struct protoent_data *protoent_data"
59.Ft void
60.Fn setprotoent "int stayopen"
61.Ft void
62.Fn setprotoent_r "int stayopen" "struct protoent_data *protoent_data"
63.Ft void
64.Fn endprotoent "void"
65.Ft void
66.Fn endprotoent_r "struct protoent_data *protoent_data"
67.Sh DESCRIPTION
68The
69.Fn getprotoent ,
70.Fn getprotobyname ,
71and
72.Fn getprotobynumber
73functions each return a pointer to an object with the following structure
74containing the broken-out fields of a line in the network protocol database,
75.Pa /etc/protocols .
76.Bd -literal -offset indent
77.Pp
78struct protoent {
79 char *p_name; /* official name of protocol */
80 char **p_aliases; /* alias list */
81 int p_proto; /* protocol number */
82};
83.Ed
84.Pp
85The members of this structure are:
86.Bl -tag -width p_aliases
87.It Fa p_name
88The official name of the protocol.
89.It Fa p_aliases
90A zero-terminated list of alternate names for the protocol.
91.It Fa p_proto
92The protocol number.
93.El
94.Pp
95The
96.Fn getprotoent
97function reads the next line of the file, opening the file if necessary.
98.Pp
99The
100.Fn setprotoent
101function opens and rewinds the file.
102If the
103.Fa stayopen
104flag is non-zero,
105the net database will not be closed after each call to
106.Fn getprotobyname
107or
108.Fn getprotobynumber .
109.Pp
110The
111.Fn endprotoent
112function closes the file.
113.Pp
114The
115.Fn getprotobyname
116and
117.Fn getprotobynumber
118functions sequentially search from the beginning of the file until a
119matching protocol name or protocol number is found, or until
120.Dv EOF
121is encountered.
122.Pp
123The
124.Fn getprotoent_r ,
125.Fn getprotobyport_r ,
126.Fn getprotobyname_r ,
127.Fn setprotoent_r ,
128and
129.Fn endprotoent_r
130functions are reentrant versions of the above functions that take a
131pointer to a
132.Fa protoent_data
133structure which is used to store state information.
134The structure must be zero-filled before it is used
135and should be considered opaque for the sake of portability.
136.Pp
137The
138.Fn getprotoent_r ,
139.Fn getprotobyport_r ,
140and
141.Fn getprotobyname_r
142functions
143also take a pointer to a
144.Fa protoent
145structure which is used to store the results of the database lookup.
146.Sh RETURN VALUES
147The
148.Fn getprotoent ,
149.Fn getprotobyport ,
150and
151.Fn getprotobyname
152functions return a pointer to a
153.Fa servent
154structure on success or a null pointer if end-of-file
155is reached or an error occurs.
156.Pp
157The
158.Fn getprotoent_r ,
159.Fn getprotobyport_r ,
160and
161.Fn getprotobyname_r
162functions return 0 on success or \-1 if end-of-file
163is reached or an error occurs.
164.Sh FILES
165.Bl -tag -width /etc/protocols -compact
166.It Pa /etc/protocols
167.El
168.Sh SEE ALSO
169.Xr protocols 5
170.Sh STANDARDS
171The
172.Fn getprotoent ,
173.Fn getprotobynumber ,
174.Fn getprotobyname ,
175.Fn setprotoent ,
176and
177.Fn endprotoent
178functions conform to
179.St -p1003.1-2003 .
180.Pp
181The
182.Fn getprotoent_r ,
183.Fn getprotobyport_r ,
184.Fn getprotobyname_r ,
185.Fn setprotoent_r ,
186and
187.Fn endprotoent_r
188functions are not currently standardized.
189This implementation follows the API used by HP, IBM and Digital.
190.Sh HISTORY
191The
192.Fn getprotoent ,
193.Fn getprotobynumber ,
194.Fn getprotobyname ,
195.Fn setprotoent ,
196and
197.Fn endprotoent
198functions appeared in
199.Bx 4.2 .
200.Pp
201The
202.Fn getprotoent_r ,
203.Fn getprotobyport_r ,
204.Fn getprotobyname_r ,
205.Fn setprotoent_r ,
206and
207.Fn endprotoent_r
208functions appeared in
209.Ox 3.7 .
210.Sh BUGS
211The non-reentrant functions use a static data space; if the data is needed
212for future use, it should be copied before any subsequent calls overwrite it.
213Only the Internet protocols are currently understood.
diff --git a/src/lib/libc/net/getprotoent.c b/src/lib/libc/net/getprotoent.c
new file mode 100644
index 0000000000..7e93d233ef
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.c
@@ -0,0 +1,168 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.7 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <errno.h>
38#include <netdb.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43void
44setprotoent_r(int f, struct protoent_data *pd)
45{
46 if (pd->fp == NULL)
47 pd->fp = fopen(_PATH_PROTOCOLS, "r" );
48 else
49 rewind(pd->fp);
50 pd->stayopen |= f;
51}
52
53void
54endprotoent_r(struct protoent_data *pd)
55{
56 if (pd->fp) {
57 fclose(pd->fp);
58 pd->fp = NULL;
59 }
60 free(pd->aliases);
61 pd->aliases = NULL;
62 pd->maxaliases = 0;
63 free(pd->line);
64 pd->line = NULL;
65 pd->stayopen = 0;
66}
67
68int
69getprotoent_r(struct protoent *pe, struct protoent_data *pd)
70{
71 char *p, *cp, **q, *endp;
72 size_t len;
73 long l;
74 int serrno;
75
76 if (pd->fp == NULL && (pd->fp = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
77 return (-1);
78again:
79 if ((p = fgetln(pd->fp, &len)) == NULL)
80 return (-1);
81 if (len == 0 || *p == '#' || *p == '\n')
82 goto again;
83 if (p[len-1] == '\n')
84 len--;
85 if ((cp = memchr(p, '#', len)) != NULL)
86 len = cp - p;
87 cp = realloc(pd->line, len + 1);
88 if (cp == NULL)
89 return (-1);
90 pd->line = pe->p_name = memcpy(cp, p, len);
91 cp[len] = '\0';
92 cp = strpbrk(cp, " \t");
93 if (cp == NULL)
94 goto again;
95 *cp++ = '\0';
96 while (*cp == ' ' || *cp == '\t')
97 cp++;
98 p = strpbrk(cp, " \t");
99 if (p != NULL)
100 *p++ = '\0';
101 l = strtol(cp, &endp, 10);
102 if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
103 goto again;
104 pe->p_proto = l;
105 if (pd->aliases == NULL) {
106 pd->maxaliases = 5;
107 pd->aliases = malloc(pd->maxaliases * sizeof(char *));
108 if (pd->aliases == NULL) {
109 serrno = errno;
110 endprotoent_r(pd);
111 errno = serrno;
112 return (-1);
113 }
114 }
115 q = pe->p_aliases = pd->aliases;
116 if (p != NULL) {
117 cp = p;
118 while (cp && *cp) {
119 if (*cp == ' ' || *cp == '\t') {
120 cp++;
121 continue;
122 }
123 if (q == &pe->p_aliases[pd->maxaliases - 1]) {
124 p = realloc(pe->p_aliases,
125 2 * pd->maxaliases * sizeof(char *));
126 if (p == NULL) {
127 serrno = errno;
128 endprotoent_r(pd);
129 errno = serrno;
130 return (-1);
131 }
132 pd->maxaliases *= 2;
133 q = (char **)p + (q - pe->p_aliases);
134 pe->p_aliases = pd->aliases = (char **)p;
135 }
136 *q++ = cp;
137 cp = strpbrk(cp, " \t");
138 if (cp != NULL)
139 *cp++ = '\0';
140 }
141 }
142 *q = NULL;
143 return (0);
144}
145
146struct protoent_data _protoent_data; /* shared with getproto{,name}.c */
147
148void
149setprotoent(int f)
150{
151 setprotoent_r(f, &_protoent_data);
152}
153
154void
155endprotoent(void)
156{
157 endprotoent_r(&_protoent_data);
158}
159
160struct protoent *
161getprotoent(void)
162{
163 static struct protoent proto;
164
165 if (getprotoent_r(&proto, &_protoent_data) != 0)
166 return (NULL);
167 return (&proto);
168}
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
new file mode 100644
index 0000000000..f257bf4a71
--- /dev/null
+++ b/src/lib/libc/net/getprotoname.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.6 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <stdio.h>
36#include <string.h>
37
38int
39getprotobyname_r(const char *name, struct protoent *pe,
40 struct protoent_data *pd)
41{
42 char **cp;
43 int error;
44
45 setprotoent_r(pd->stayopen, pd);
46 while ((error = getprotoent_r(pe, pd)) == 0) {
47 if (strcmp(pe->p_name, name) == 0)
48 break;
49 for (cp = pe->p_aliases; *cp != 0; cp++)
50 if (strcmp(*cp, name) == 0)
51 goto found;
52 }
53found:
54 if (!pd->stayopen && pd->fp != NULL) {
55 fclose(pd->fp);
56 pd->fp = NULL;
57 }
58 return (error);
59}
60
61struct protoent *
62getprotobyname(const char *name)
63{
64 extern struct protoent_data _protoent_data;
65 static struct protoent proto;
66
67 if (getprotobyname_r(name, &proto, &_protoent_data) != 0)
68 return (NULL);
69 return (&proto);
70}
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..621ff31b81
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.13 2005/02/25 03:12:43 cloder Exp $
2.\"
3.\" Copyright (C) 2000, 2001 Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM
10.\" DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
11.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12.\" INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
13.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\"
18.Dd October 18, 2000
19.Dt GETRRSETBYNAME 3
20.Os
21.Sh NAME
22.Nm getrrsetbyname
23.Nd retrieve DNS records
24.Sh SYNOPSIS
25.Fd #include <netdb.h>
26.Ft int
27.Fn getrrsetbyname "const char *hostname" "unsigned int rdclass" \
28"unsigned int rdtype" "unsigned int flags" "struct rrsetinfo **res"
29.Ft void
30.Fn freerrset "struct rrsetinfo *rrset"
31.Sh DESCRIPTION
32.Fn getrrsetbyname
33gets a set of resource records associated with a
34.Fa hostname ,
35.Fa rdclass
36and
37.Fa rdtype .
38.Fa hostname
39is a pointer to a NUL-terminated string.
40The
41.Fa flags
42field is currently unused and must be zero.
43.Pp
44After a successful call to
45.Fn getrrsetbyname ,
46.Fa *res
47is a pointer to an
48.Li rrsetinfo
49structure, containing a list of one or more
50.Li rdatainfo
51structures containing resource records and potentially another list of
52.Li rdatainfo
53structures containing SIG resource records associated with those records.
54The members
55.Li rri_rdclass
56and
57.Li rri_rdtype
58are copied from the parameters.
59.Li rri_ttl
60and
61.Li rri_name
62are properties of the obtained rrset.
63The resource records contained in
64.Li rri_rdatas
65and
66.Li rri_sigs
67are in uncompressed DNS wire format.
68Properties of the rdataset are represented in the
69.Li rri_flags
70bitfield.
71If the
72.Dv RRSET_VALIDATED
73bit is set, the data has been DNSSEC
74validated and the signatures verified.
75.Pp
76The following structures are used:
77.Bd -literal -offset
78struct rdatainfo {
79 unsigned int rdi_length; /* length of data */
80 unsigned char *rdi_data; /* record data */
81};
82
83struct rrsetinfo {
84 unsigned int rri_flags; /* RRSET_VALIDATED ... */
85 unsigned int rri_rdclass; /* class number */
86 unsigned int rri_rdtype; /* RR type number */
87 unsigned int rri_ttl; /* time to live */
88 unsigned int rri_nrdatas; /* size of rdatas array */
89 unsigned int rri_nsigs; /* size of sigs array */
90 char *rri_name; /* canonical name */
91 struct rdatainfo *rri_rdatas; /* individual records */
92 struct rdatainfo *rri_sigs; /* individual signatures */
93};
94.Ed
95.Pp
96All of the information returned by
97.Fn getrrsetbyname
98is dynamically allocated: the
99.Li rrsetinfo
100and
101.Li rdatainfo
102structures,
103and the canonical host name strings pointed to by the
104.Li rrsetinfo
105structure.
106Memory allocated for the dynamically allocated structures created by
107a successful call to
108.Fn getrrsetbyname
109is released by
110.Fn freerrset .
111.Li rrset
112is a pointer to a
113.Li struct rrset
114created by a call to
115.Fn getrrsetbyname .
116.Pp
117If the EDNS0 option is activated in
118.Xr resolv.conf 5 ,
119.Fn getrrsetbyname
120will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
121.Sh RETURN VALUES
122.Fn getrrsetbyname
123returns zero on success, and one of the following error
124codes if an error occurred:
125.Pp
126.Bl -tag -width ERRSET_NOMEMORY -compact
127.It Dv ERRSET_NONAME
128the name does not exist
129.It Dv ERRSET_NODATA
130the name exists, but does not have data of the desired type
131.It Dv ERRSET_NOMEMORY
132memory could not be allocated
133.It Dv ERRSET_INVAL
134a parameter is invalid
135.It Dv ERRSET_FAIL
136other failure
137.El
138.Sh SEE ALSO
139.Xr resolver 3 ,
140.Xr resolv.conf 5 ,
141.Xr named 8
142.Sh HISTORY
143.Fn getrrsetbyname
144first appeared in
145.Ox 3.0 .
146The API first appeared in ISC BIND version 9.
147.Sh AUTHORS
148.An Jakob Schlyter Aq jakob@openbsd.org
149.Sh CAVEATS
150The
151.Dv RRSET_VALIDATED
152flag in
153.Li rri_flags
154is set if the AD (authenticated data) bit in the DNS answer is
155set.
156This flag
157.Em should not
158be trusted unless the transport between the nameserver and the resolver
159is secure (e.g. IPsec, trusted network, loopback communication).
160.Sh BUGS
161The data in
162.Li *rdi_data
163should be returned in uncompressed wire format.
164Currently, the data is in compressed format and the caller can't
165uncompress since it doesn't have the full message.
diff --git a/src/lib/libc/net/getrrsetbyname.c b/src/lib/libc/net/getrrsetbyname.c
new file mode 100644
index 0000000000..e679eb5d96
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,514 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * Copyright (c) 2001 Jakob Schlyter. 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 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Portions Copyright (c) 1999-2001 Internet Software Consortium.
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
37 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
39 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
40 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
41 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
42 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
43 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <sys/types.h>
47#include <netinet/in.h>
48#include <arpa/nameser.h>
49#include <netdb.h>
50#include <resolv.h>
51#include <stdlib.h>
52#include <string.h>
53
54#include "thread_private.h"
55
56#define ANSWER_BUFFER_SIZE 1024*64
57
58struct dns_query {
59 char *name;
60 u_int16_t type;
61 u_int16_t class;
62 struct dns_query *next;
63};
64
65struct dns_rr {
66 char *name;
67 u_int16_t type;
68 u_int16_t class;
69 u_int16_t ttl;
70 u_int16_t size;
71 void *rdata;
72 struct dns_rr *next;
73};
74
75struct dns_response {
76 HEADER header;
77 struct dns_query *query;
78 struct dns_rr *answer;
79 struct dns_rr *authority;
80 struct dns_rr *additional;
81};
82
83static struct dns_response *parse_dns_response(const u_char *, int);
84static struct dns_query *parse_dns_qsection(const u_char *, int,
85 const u_char **, int);
86static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
87 int);
88
89static void free_dns_query(struct dns_query *);
90static void free_dns_rr(struct dns_rr *);
91static void free_dns_response(struct dns_response *);
92
93static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
94
95int
96getrrsetbyname(const char *hostname, unsigned int rdclass,
97 unsigned int rdtype, unsigned int flags,
98 struct rrsetinfo **res)
99{
100 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
101 int result;
102 struct rrsetinfo *rrset = NULL;
103 struct dns_response *response = NULL;
104 struct dns_rr *rr;
105 struct rdatainfo *rdata;
106 int length;
107 unsigned int index_ans, index_sig;
108 u_char answer[ANSWER_BUFFER_SIZE];
109
110 /* check for invalid class and type */
111 if (rdclass > 0xffff || rdtype > 0xffff) {
112 result = ERRSET_INVAL;
113 goto fail;
114 }
115
116 /* don't allow queries of class or type ANY */
117 if (rdclass == 0xff || rdtype == 0xff) {
118 result = ERRSET_INVAL;
119 goto fail;
120 }
121
122 /* don't allow flags yet, unimplemented */
123 if (flags) {
124 result = ERRSET_INVAL;
125 goto fail;
126 }
127
128 /* initialize resolver */
129 if (_res_init(0) == -1) {
130 result = ERRSET_FAIL;
131 goto fail;
132 }
133
134#ifdef DEBUG
135 _resp->options |= RES_DEBUG;
136#endif /* DEBUG */
137
138#ifdef RES_USE_DNSSEC
139 /* turn on DNSSEC if EDNS0 is configured */
140 if (_resp->options & RES_USE_EDNS0)
141 _resp->options |= RES_USE_DNSSEC;
142#endif /* RES_USE_DNSEC */
143
144 /* make query */
145 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
146 answer, sizeof(answer));
147 if (length < 0) {
148 switch(h_errno) {
149 case HOST_NOT_FOUND:
150 result = ERRSET_NONAME;
151 goto fail;
152 case NO_DATA:
153 result = ERRSET_NODATA;
154 goto fail;
155 default:
156 result = ERRSET_FAIL;
157 goto fail;
158 }
159 }
160
161 /* parse result */
162 response = parse_dns_response(answer, length);
163 if (response == NULL) {
164 result = ERRSET_FAIL;
165 goto fail;
166 }
167
168 if (response->header.qdcount != 1) {
169 result = ERRSET_FAIL;
170 goto fail;
171 }
172
173 /* initialize rrset */
174 rrset = calloc(1, sizeof(struct rrsetinfo));
175 if (rrset == NULL) {
176 result = ERRSET_NOMEMORY;
177 goto fail;
178 }
179 rrset->rri_rdclass = response->query->class;
180 rrset->rri_rdtype = response->query->type;
181 rrset->rri_ttl = response->answer->ttl;
182 rrset->rri_nrdatas = response->header.ancount;
183
184 /* check for authenticated data */
185 if (response->header.ad == 1)
186 rrset->rri_flags |= RRSET_VALIDATED;
187
188 /* copy name from answer section */
189 rrset->rri_name = strdup(response->answer->name);
190 if (rrset->rri_name == NULL) {
191 result = ERRSET_NOMEMORY;
192 goto fail;
193 }
194
195 /* count answers */
196 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
197 rrset->rri_rdtype);
198 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
199 T_SIG);
200
201 /* allocate memory for answers */
202 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
203 sizeof(struct rdatainfo));
204 if (rrset->rri_rdatas == NULL) {
205 result = ERRSET_NOMEMORY;
206 goto fail;
207 }
208
209 /* allocate memory for signatures */
210 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
211 if (rrset->rri_sigs == NULL) {
212 result = ERRSET_NOMEMORY;
213 goto fail;
214 }
215
216 /* copy answers & signatures */
217 for (rr = response->answer, index_ans = 0, index_sig = 0;
218 rr; rr = rr->next) {
219
220 rdata = NULL;
221
222 if (rr->class == rrset->rri_rdclass &&
223 rr->type == rrset->rri_rdtype)
224 rdata = &rrset->rri_rdatas[index_ans++];
225
226 if (rr->class == rrset->rri_rdclass &&
227 rr->type == T_SIG)
228 rdata = &rrset->rri_sigs[index_sig++];
229
230 if (rdata) {
231 rdata->rdi_length = rr->size;
232 rdata->rdi_data = malloc(rr->size);
233
234 if (rdata->rdi_data == NULL) {
235 result = ERRSET_NOMEMORY;
236 goto fail;
237 }
238 memcpy(rdata->rdi_data, rr->rdata, rr->size);
239 }
240 }
241 free_dns_response(response);
242
243 *res = rrset;
244 return (ERRSET_SUCCESS);
245
246fail:
247 if (rrset != NULL)
248 freerrset(rrset);
249 if (response != NULL)
250 free_dns_response(response);
251 return (result);
252}
253
254void
255freerrset(struct rrsetinfo *rrset)
256{
257 u_int16_t i;
258
259 if (rrset == NULL)
260 return;
261
262 if (rrset->rri_rdatas) {
263 for (i = 0; i < rrset->rri_nrdatas; i++) {
264 if (rrset->rri_rdatas[i].rdi_data == NULL)
265 break;
266 free(rrset->rri_rdatas[i].rdi_data);
267 }
268 free(rrset->rri_rdatas);
269 }
270
271 if (rrset->rri_sigs) {
272 for (i = 0; i < rrset->rri_nsigs; i++) {
273 if (rrset->rri_sigs[i].rdi_data == NULL)
274 break;
275 free(rrset->rri_sigs[i].rdi_data);
276 }
277 free(rrset->rri_sigs);
278 }
279
280 if (rrset->rri_name)
281 free(rrset->rri_name);
282 free(rrset);
283}
284
285/*
286 * DNS response parsing routines
287 */
288static struct dns_response *
289parse_dns_response(const u_char *answer, int size)
290{
291 struct dns_response *resp;
292 const u_char *cp;
293
294 /* allocate memory for the response */
295 resp = calloc(1, sizeof(*resp));
296 if (resp == NULL)
297 return (NULL);
298
299 /* initialize current pointer */
300 cp = answer;
301
302 /* copy header */
303 memcpy(&resp->header, cp, HFIXEDSZ);
304 cp += HFIXEDSZ;
305
306 /* fix header byte order */
307 resp->header.qdcount = ntohs(resp->header.qdcount);
308 resp->header.ancount = ntohs(resp->header.ancount);
309 resp->header.nscount = ntohs(resp->header.nscount);
310 resp->header.arcount = ntohs(resp->header.arcount);
311
312 /* there must be at least one query */
313 if (resp->header.qdcount < 1) {
314 free_dns_response(resp);
315 return (NULL);
316 }
317
318 /* parse query section */
319 resp->query = parse_dns_qsection(answer, size, &cp,
320 resp->header.qdcount);
321 if (resp->header.qdcount && resp->query == NULL) {
322 free_dns_response(resp);
323 return (NULL);
324 }
325
326 /* parse answer section */
327 resp->answer = parse_dns_rrsection(answer, size, &cp,
328 resp->header.ancount);
329 if (resp->header.ancount && resp->answer == NULL) {
330 free_dns_response(resp);
331 return (NULL);
332 }
333
334 /* parse authority section */
335 resp->authority = parse_dns_rrsection(answer, size, &cp,
336 resp->header.nscount);
337 if (resp->header.nscount && resp->authority == NULL) {
338 free_dns_response(resp);
339 return (NULL);
340 }
341
342 /* parse additional section */
343 resp->additional = parse_dns_rrsection(answer, size, &cp,
344 resp->header.arcount);
345 if (resp->header.arcount && resp->additional == NULL) {
346 free_dns_response(resp);
347 return (NULL);
348 }
349
350 return (resp);
351}
352
353static struct dns_query *
354parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
355{
356 struct dns_query *head, *curr, *prev;
357 int i, length;
358 char name[MAXDNAME];
359
360 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
361
362 /* allocate and initialize struct */
363 curr = calloc(1, sizeof(struct dns_query));
364 if (curr == NULL) {
365 free_dns_query(head);
366 return (NULL);
367 }
368 if (head == NULL)
369 head = curr;
370 if (prev != NULL)
371 prev->next = curr;
372
373 /* name */
374 length = dn_expand(answer, answer + size, *cp, name,
375 sizeof(name));
376 if (length < 0) {
377 free_dns_query(head);
378 return (NULL);
379 }
380 curr->name = strdup(name);
381 if (curr->name == NULL) {
382 free_dns_query(head);
383 return (NULL);
384 }
385 *cp += length;
386
387 /* type */
388 curr->type = _getshort(*cp);
389 *cp += INT16SZ;
390
391 /* class */
392 curr->class = _getshort(*cp);
393 *cp += INT16SZ;
394 }
395
396 return (head);
397}
398
399static struct dns_rr *
400parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
401 int count)
402{
403 struct dns_rr *head, *curr, *prev;
404 int i, length;
405 char name[MAXDNAME];
406
407 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
408
409 /* allocate and initialize struct */
410 curr = calloc(1, sizeof(struct dns_rr));
411 if (curr == NULL) {
412 free_dns_rr(head);
413 return (NULL);
414 }
415 if (head == NULL)
416 head = curr;
417 if (prev != NULL)
418 prev->next = curr;
419
420 /* name */
421 length = dn_expand(answer, answer + size, *cp, name,
422 sizeof(name));
423 if (length < 0) {
424 free_dns_rr(head);
425 return (NULL);
426 }
427 curr->name = strdup(name);
428 if (curr->name == NULL) {
429 free_dns_rr(head);
430 return (NULL);
431 }
432 *cp += length;
433
434 /* type */
435 curr->type = _getshort(*cp);
436 *cp += INT16SZ;
437
438 /* class */
439 curr->class = _getshort(*cp);
440 *cp += INT16SZ;
441
442 /* ttl */
443 curr->ttl = _getlong(*cp);
444 *cp += INT32SZ;
445
446 /* rdata size */
447 curr->size = _getshort(*cp);
448 *cp += INT16SZ;
449
450 /* rdata itself */
451 curr->rdata = malloc(curr->size);
452 if (curr->rdata == NULL) {
453 free_dns_rr(head);
454 return (NULL);
455 }
456 memcpy(curr->rdata, *cp, curr->size);
457 *cp += curr->size;
458 }
459
460 return (head);
461}
462
463static void
464free_dns_query(struct dns_query *p)
465{
466 if (p == NULL)
467 return;
468
469 if (p->name)
470 free(p->name);
471 free_dns_query(p->next);
472 free(p);
473}
474
475static void
476free_dns_rr(struct dns_rr *p)
477{
478 if (p == NULL)
479 return;
480
481 if (p->name)
482 free(p->name);
483 if (p->rdata)
484 free(p->rdata);
485 free_dns_rr(p->next);
486 free(p);
487}
488
489static void
490free_dns_response(struct dns_response *p)
491{
492 if (p == NULL)
493 return;
494
495 free_dns_query(p->query);
496 free_dns_rr(p->answer);
497 free_dns_rr(p->authority);
498 free_dns_rr(p->additional);
499 free(p);
500}
501
502static int
503count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
504{
505 int n = 0;
506
507 while(p) {
508 if (p->class == class && p->type == type)
509 n++;
510 p = p->next;
511 }
512
513 return (n);
514}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
new file mode 100644
index 0000000000..062318630f
--- /dev/null
+++ b/src/lib/libc/net/getservbyname.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.9 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <stdio.h>
36#include <string.h>
37
38int
39getservbyname_r(const char *name, const char *proto, struct servent *se,
40 struct servent_data *sd)
41{
42 char **cp;
43 int error;
44
45 setservent_r(sd->stayopen, sd);
46 while ((error = getservent_r(se, sd)) == 0) {
47 if (strcmp(name, se->s_name) == 0)
48 goto gotname;
49 for (cp = se->s_aliases; *cp; cp++)
50 if (strcmp(name, *cp) == 0)
51 goto gotname;
52 continue;
53gotname:
54 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
55 break;
56 }
57 if (!sd->stayopen && sd->fp != NULL) {
58 fclose(sd->fp);
59 sd->fp = NULL;
60 }
61 return (error);
62}
63
64struct servent *
65getservbyname(const char *name, const char *proto)
66{
67 extern struct servent_data _servent_data;
68 static struct servent serv;
69
70 if (getservbyname_r(name, proto, &serv, &_servent_data) != 0)
71 return (NULL);
72 return (&serv);
73}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
new file mode 100644
index 0000000000..5e210b2e8b
--- /dev/null
+++ b/src/lib/libc/net/getservbyport.c
@@ -0,0 +1,67 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.6 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <stdio.h>
36#include <string.h>
37
38int
39getservbyport_r(int port, const char *proto, struct servent *se,
40 struct servent_data *sd)
41{
42 int error;
43
44 setservent_r(sd->stayopen, sd);
45 while ((error = getservent_r(se, sd)) == 0) {
46 if (se->s_port != port)
47 continue;
48 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
49 break;
50 }
51 if (!sd->stayopen && sd->fp != NULL) {
52 fclose(sd->fp);
53 sd->fp = NULL;
54 }
55 return (error);
56}
57
58struct servent *
59getservbyport(int port, const char *proto)
60{
61 extern struct servent_data _servent_data;
62 static struct servent serv;
63
64 if (getservbyport_r(port, proto, &serv, &_servent_data) != 0)
65 return (NULL);
66 return (&serv);
67}
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
new file mode 100644
index 0000000000..d5fa1df052
--- /dev/null
+++ b/src/lib/libc/net/getservent.3
@@ -0,0 +1,220 @@
1.\" $OpenBSD: getservent.3,v 1.16 2004/10/26 15:52:50 millert Exp $
2.\"
3.\" Copyright (c) 1983, 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 October 13, 2004
31.Dt GETSERVENT 3
32.Os
33.Sh NAME
34.Nm getservent ,
35.Nm getservent_r ,
36.Nm getservbyport ,
37.Nm getservbyport_r ,
38.Nm getservbyname ,
39.Nm getservbyname_r ,
40.Nm setservent ,
41.Nm setservent_r ,
42.Nm endservent ,
43.Nm endservent_r
44.Nd get service entry
45.Sh SYNOPSIS
46.Fd #include <netdb.h>
47.Ft struct servent *
48.Fn getservent "void"
49.Ft int
50.Fn getservent_r "struct servent *servent" "struct servent_data *servent_data"
51.Ft struct servent *
52.Fn getservbyname "const char *name" "const char *proto"
53.Ft int
54.Fn getservbyname_r "const char *name" "const char *proto" "struct servent *servent" "struct servent_data *servent_data"
55.Ft struct servent *
56.Fn getservbyport "int port" "const char *proto"
57.Ft int
58.Fn getservbyport_r "int port" "const char *proto" "struct servent *servent" "struct servent_data *servent_data"
59.Ft void
60.Fn setservent "int stayopen"
61.Ft void
62.Fn setservent_r "int stayopen" "struct servent_data *servent_data"
63.Ft void
64.Fn endservent "void"
65.Ft void
66.Fn endservent_r "struct servent_data *servent_data"
67.Sh DESCRIPTION
68The
69.Fn getservent ,
70.Fn getservbyname ,
71and
72.Fn getservbyport
73functions each return a pointer to an object with the following structure
74containing the broken-out fields of a line in the network services database,
75.Pa /etc/services .
76.Bd -literal -offset indent
77struct servent {
78 char *s_name; /* official name of service */
79 char **s_aliases; /* alias list */
80 int s_port; /* port service resides at */
81 char *s_proto; /* protocol to use */
82};
83.Ed
84.Pp
85The members of this structure are:
86.Bl -tag -width s_aliases
87.It Fa s_name
88The official name of the service.
89.It Fa s_aliases
90A zero-terminated list of alternate names for the service.
91.It Fa s_port
92The port number at which the service resides.
93Port numbers are returned in network byte order.
94.It Fa s_proto
95The name of the protocol to use when contacting the service.
96.El
97.Pp
98The
99.Fn getservent
100function reads the next line of the file, opening the file if necessary.
101.Pp
102The
103.Fn setservent
104function opens and rewinds the file.
105If the
106.Fa stayopen
107flag is non-zero,
108the net database will not be closed after each call to
109.Fn getservbyname
110or
111.Fn getservbyport .
112.Pp
113The
114.Fn endservent
115function closes the file.
116.Pp
117The
118.Fn getservbyname
119and
120.Fn getservbyport
121functions sequentially search from the beginning of the file until a
122matching protocol name or port number (specified in network byte order)
123is found, or until
124.Dv EOF
125is encountered.
126If a protocol name is also supplied (non-null),
127searches must also match the protocol.
128.Pp
129The
130.Fn getservent_r ,
131.Fn getservbyport_r ,
132.Fn getservbyname_r ,
133.Fn setservent_r ,
134and
135.Fn endservent_r
136functions are reentrant versions of the above functions that take a
137pointer to a
138.Fa servent_data
139structure which is used to store state information.
140The structure must be zero-filled before it is used
141and should be considered opaque for the sake of portability.
142.Pp
143The
144.Fn getservent_r ,
145.Fn getservbyport_r ,
146and
147.Fn getservbyname_r
148functions
149also take a pointer to a
150.Fa servent
151structure which is used to store the results of the database lookup.
152.Sh FILES
153.Bl -tag -width /etc/services -compact
154.It Pa /etc/services
155.El
156.Sh RETURN VALUES
157The
158.Fn getservent ,
159.Fn getservbyport ,
160and
161.Fn getservbyname
162functions return a pointer to a
163.Fa servent
164structure on success or a null pointer if end-of-file
165is reached or an error occurs.
166.Pp
167The
168.Fn getservent_r ,
169.Fn getservbyport_r ,
170and
171.Fn getservbyname_r
172functions return 0 on success or \-1 if end-of-file
173is reached or an error occurs.
174.Sh SEE ALSO
175.Xr getprotoent 3 ,
176.Xr services 5
177.Sh STANDARDS
178The
179.Fn getservent ,
180.Fn getservbynumber ,
181.Fn getservbyname ,
182.Fn setservent ,
183and
184.Fn endservent
185functions conform to
186.St -p1003.1-2003 .
187.Pp
188The
189.Fn getservent_r ,
190.Fn getservbyport_r ,
191.Fn getservbyname_r ,
192.Fn setservent_r ,
193and
194.Fn endservent_r
195functions are not currently standardized.
196This implementation follows the API used by HP, IBM and Digital.
197.Sh HISTORY
198The
199.Fn getservent ,
200.Fn getservbyport ,
201.Fn getservbyname ,
202.Fn setservent ,
203and
204.Fn endservent
205functions appeared in
206.Pp
207.Bx 4.2 .
208The
209.Fn getservent_r ,
210.Fn getservbyport_r ,
211.Fn getservbyname_r ,
212.Fn setservent_r ,
213and
214.Fn endservent_r
215functions appeared in
216.Ox 3.7 .
217.Sh BUGS
218The non-reentrant functions use static data storage; if the data is needed
219for future use, it should be copied before any subsequent calls overwrite it.
220Expecting port numbers to fit in a 32-bit quantity is probably naive.
diff --git a/src/lib/libc/net/getservent.c b/src/lib/libc/net/getservent.c
new file mode 100644
index 0000000000..3eaf2a4adc
--- /dev/null
+++ b/src/lib/libc/net/getservent.c
@@ -0,0 +1,170 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservent.c,v 1.9 2004/10/25 03:09:01 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <errno.h>
38#include <netdb.h>
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42
43void
44setservent_r(int f, struct servent_data *sd)
45{
46 if (sd->fp == NULL)
47 sd->fp = fopen(_PATH_SERVICES, "r" );
48 else
49 rewind(sd->fp);
50 sd->stayopen |= f;
51}
52
53void
54endservent_r(struct servent_data *sd)
55{
56 if (sd->fp) {
57 fclose(sd->fp);
58 sd->fp = NULL;
59 }
60 free(sd->aliases);
61 sd->aliases = NULL;
62 sd->maxaliases = 0;
63 free(sd->line);
64 sd->line = NULL;
65 sd->stayopen = 0;
66}
67
68int
69getservent_r(struct servent *se, struct servent_data *sd)
70{
71 char *p, *cp, **q, *endp;
72 size_t len;
73 long l;
74 int serrno;
75
76 if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r" )) == NULL)
77 return (-1);
78again:
79 if ((p = fgetln(sd->fp, &len)) == NULL)
80 return (-1);
81 if (len == 0 || *p == '#' || *p == '\n')
82 goto again;
83 if (p[len-1] == '\n')
84 len--;
85 if ((cp = memchr(p, '#', len)) != NULL)
86 len = cp - p;
87 cp = realloc(sd->line, len + 1);
88 if (cp == NULL)
89 return (-1);
90 sd->line = se->s_name = memcpy(cp, p, len);
91 cp[len] = '\0';
92 p = strpbrk(cp, " \t");
93 if (p == NULL)
94 goto again;
95 *p++ = '\0';
96 while (*p == ' ' || *p == '\t')
97 p++;
98 cp = strpbrk(p, ",/");
99 if (cp == NULL)
100 goto again;
101 *cp++ = '\0';
102 l = strtol(p, &endp, 10);
103 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
104 goto again;
105 se->s_port = htons((in_port_t)l);
106 se->s_proto = cp;
107 if (sd->aliases == NULL) {
108 sd->maxaliases = 10;
109 sd->aliases = malloc(sd->maxaliases * sizeof(char *));
110 if (sd->aliases == NULL) {
111 serrno = errno;
112 endservent_r(sd);
113 errno = serrno;
114 return (-1);
115 }
116 }
117 q = se->s_aliases = sd->aliases;
118 cp = strpbrk(cp, " \t");
119 if (cp != NULL)
120 *cp++ = '\0';
121 while (cp && *cp) {
122 if (*cp == ' ' || *cp == '\t') {
123 cp++;
124 continue;
125 }
126 if (q == &se->s_aliases[sd->maxaliases - 1]) {
127 p = realloc(se->s_aliases,
128 2 * sd->maxaliases * sizeof(char *));
129 if (p == NULL) {
130 serrno = errno;
131 endservent_r(sd);
132 errno = serrno;
133 return (-1);
134 }
135 sd->maxaliases *= 2;
136 q = (char **)p + (q - se->s_aliases);
137 se->s_aliases = sd->aliases = (char **)p;
138 }
139 *q++ = cp;
140 cp = strpbrk(cp, " \t");
141 if (cp != NULL)
142 *cp++ = '\0';
143 }
144 *q = NULL;
145 return (0);
146}
147
148struct servent_data _servent_data; /* shared with getservby{name,port}.c */
149
150void
151setservent(int f)
152{
153 setservent_r(f, &_servent_data);
154}
155
156void
157endservent(void)
158{
159 endservent_r(&_servent_data);
160}
161
162struct servent *
163getservent(void)
164{
165 static struct servent serv;
166
167 if (getservent_r(&serv, &_servent_data) != 0)
168 return (NULL);
169 return (&serv);
170}
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
new file mode 100644
index 0000000000..c1e5a4ba56
--- /dev/null
+++ b/src/lib/libc/net/herror.c
@@ -0,0 +1,115 @@
1/* $OpenBSD: herror.c,v 1.7 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * ++Copyright++ 1987, 1993
5 * -
6 * Copyright (c) 1987, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: herror.c,v 1.7 2005/03/25 13:24:12 otto Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <sys/uio.h>
66#include <netdb.h>
67#include <unistd.h>
68#include <string.h>
69
70const char * const h_errlist[] = {
71 "Resolver Error 0 (no error)",
72 "Unknown host", /* 1 HOST_NOT_FOUND */
73 "Host name lookup failure", /* 2 TRY_AGAIN */
74 "Unknown server error", /* 3 NO_RECOVERY */
75 "No address associated with name", /* 4 NO_ADDRESS */
76};
77const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
78
79extern int h_errno;
80
81/*
82 * herror --
83 * print the error indicated by the h_errno value.
84 */
85void
86herror(const char *s)
87{
88 struct iovec iov[4];
89 struct iovec *v = iov;
90
91 if (s && *s) {
92 v->iov_base = (char *)s;
93 v->iov_len = strlen(s);
94 v++;
95 v->iov_base = ": ";
96 v->iov_len = 2;
97 v++;
98 }
99 v->iov_base = (char *)hstrerror(h_errno);
100 v->iov_len = strlen(v->iov_base);
101 v++;
102 v->iov_base = "\n";
103 v->iov_len = 1;
104 writev(STDERR_FILENO, iov, (v - iov) + 1);
105}
106
107const char *
108hstrerror(int err)
109{
110 if (err < 0)
111 return ("Resolver internal error");
112 else if (err < h_nerr)
113 return (h_errlist[err]);
114 return ("Unknown resolver error");
115}
diff --git a/src/lib/libc/net/htonl.c b/src/lib/libc/net/htonl.c
new file mode 100644
index 0000000000..f104e190a2
--- /dev/null
+++ b/src/lib/libc/net/htonl.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: htonl.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef htonl
14
15u_int32_t
16htonl(u_int32_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *)&x;
20 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/htons.c b/src/lib/libc/net/htons.c
new file mode 100644
index 0000000000..ded70712ea
--- /dev/null
+++ b/src/lib/libc/net/htons.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: htons.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef htons
14
15u_int16_t
16htons(u_int16_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *) &x;
20 return (u_int16_t)(s[0] << 8 | s[1]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/if_indextoname.3 b/src/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000000..e7bfde4900
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,136 @@
1.\" $OpenBSD: if_indextoname.3,v 1.8 2005/02/25 03:12:43 cloder Exp $
2.\" Copyright (c) 1983, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. Neither the name of the University nor the names of its contributors
14.\" may be used to endorse or promote products derived from this software
15.\" without specific prior written permission.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27.\" SUCH DAMAGE.
28.\"
29.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
30.\"
31.Dd May 21, 1998
32.Dt IF_NAMETOINDEX 3
33.Os
34.Sh NAME
35.Nm if_nametoindex ,
36.Nm if_indextoname ,
37.Nm if_nameindex ,
38.Nm if_freenameindex
39.Nd convert interface index to name, and vice versa
40.Sh SYNOPSIS
41.Fd #include <net/if.h>
42.Ft "unsigned int"
43.Fn if_nametoindex "const char *ifname"
44.Ft "char *"
45.Fn if_indextoname "unsigned int ifindex" "char *ifname"
46.Ft "struct if_nameindex *"
47.Fn if_nameindex "void"
48.Ft "void"
49.Fn if_freenameindex "struct if_nameindex *ptr"
50.Sh DESCRIPTION
51These functions map interface indexes to interface names (such as
52.Dq lo0 ) ,
53and vice versa.
54.Pp
55The
56.Fn if_nametoindex
57function converts an interface name specified by the
58.Fa ifname
59argument to an interface index (positive integer value).
60If the specified interface does not exist, 0 will be returned.
61.Pp
62.Fn if_indextoname
63converts an interface index specified by the
64.Fa ifindex
65argument to an interface name.
66The
67.Fa ifname
68argument must point to a buffer of at least
69.Dv IF_NAMESIZE
70bytes into which the interface name corresponding to the specified index is
71returned.
72.Pf ( Dv IF_NAMESIZE
73is also defined in
74.Aq Pa net/if.h
75and its value includes a terminating NUL byte at the end of the
76interface name.)
77This pointer is also the return value of the function.
78If there is no interface corresponding to the specified index,
79.Dv NULL
80is returned.
81.Pp
82.Fn if_nameindex
83returns an array of
84.Fa if_nameindex
85structures.
86.Fa if_nametoindex
87is also defined in
88.Aq Pa net/if.h ,
89and is as follows:
90.Bd -literal -offset
91struct if_nameindex {
92 unsigned int if_index; /* 1, 2, ... */
93 char *if_name; /* NUL-terminated name: "le0", ... */
94};
95.Ed
96.Pp
97The end of the array of structures is indicated by a structure with
98an
99.Fa if_index
100of 0 and an
101.Fa if_name
102of
103.Dv NULL .
104The function returns a null pointer on error.
105The memory used for this array of structures along with the interface
106names pointed to by the
107.Fa if_name
108members is obtained dynamically.
109This memory is freed by the
110.Fn if_freenameindex
111function.
112.Pp
113.Fn if_freenameindex
114takes a pointer that was returned by
115.Fn if_nameindex
116as argument
117.Pq Fa ptr ,
118and it reclaims the region allocated.
119.Sh DIAGNOSTICS
120.Fn if_nametoindex
121returns 0 on error, positive integer on success.
122.Fn if_indextoname
123and
124.Fn if_nameindex
125return
126.Dv NULL
127on errors.
128.Sh SEE ALSO
129.Xr getifaddrs 3 ,
130.Xr networking 4
131.Pp
132R. Gilligan, S. Thomson, J. Bound, and W. Stevens,
133``Basic Socket Interface Extensions for IPv6,'' RFC 2553, March 1999.
134.Sh STANDARDS
135These functions are defined in ``Basic Socket Interface Extensions for IPv6''
136.Pq RFC 2533 .
diff --git a/src/lib/libc/net/if_indextoname.c b/src/lib/libc/net/if_indextoname.c
new file mode 100644
index 0000000000..f99e52e387
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.c
@@ -0,0 +1,86 @@
1/* $OpenBSD: if_indextoname.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_indextoname.c,v 1.6 2000/11/07 22:33:25 jinmei Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. 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 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2533:
40 *
41 * The second function maps an interface index into its corresponding
42 * name.
43 *
44 * #include <net/if.h>
45 *
46 * char *if_indextoname(unsigned int ifindex, char *ifname);
47 *
48 * The ifname argument must point to a buffer of at least IF_NAMESIZE
49 * bytes into which the interface name corresponding to the specified
50 * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
51 * its value includes a terminating null byte at the end of the
52 * interface name.) This pointer is also the return value of the
53 * function. If there is no interface corresponding to the specified
54 * index, NULL is returned, and errno is set to ENXIO, if there was a
55 * system error (such as running out of memory), if_indextoname returns
56 * NULL and errno would be set to the proper value (e.g., ENOMEM).
57 */
58
59char *
60if_indextoname(unsigned int ifindex, char *ifname)
61{
62 struct ifaddrs *ifaddrs, *ifa;
63 int error = 0;
64
65 if (getifaddrs(&ifaddrs) < 0)
66 return(NULL); /* getifaddrs properly set errno */
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
72 break;
73 }
74
75 if (ifa == NULL) {
76 error = ENXIO;
77 ifname = NULL;
78 }
79 else
80 strlcpy(ifname, ifa->ifa_name, IFNAMSIZ);
81
82 freeifaddrs(ifaddrs);
83
84 errno = error;
85 return(ifname);
86}
diff --git a/src/lib/libc/net/if_nameindex.c b/src/lib/libc/net/if_nameindex.c
new file mode 100644
index 0000000000..3675a2a450
--- /dev/null
+++ b/src/lib/libc/net/if_nameindex.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: if_nameindex.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. 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 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36
37/*
38 * From RFC 2553:
39 *
40 * 4.3 Return All Interface Names and Indexes
41 *
42 * The if_nameindex structure holds the information about a single
43 * interface and is defined as a result of including the <net/if.h>
44 * header.
45 *
46 * struct if_nameindex {
47 * unsigned int if_index;
48 * char *if_name;
49 * };
50 *
51 * The final function returns an array of if_nameindex structures, one
52 * structure per interface.
53 *
54 * struct if_nameindex *if_nameindex(void);
55 *
56 * The end of the array of structures is indicated by a structure with
57 * an if_index of 0 and an if_name of NULL. The function returns a NULL
58 * pointer upon an error, and would set errno to the appropriate value.
59 *
60 * The memory used for this array of structures along with the interface
61 * names pointed to by the if_name members is obtained dynamically.
62 * This memory is freed by the next function.
63 *
64 * 4.4. Free Memory
65 *
66 * The following function frees the dynamic memory that was allocated by
67 * if_nameindex().
68 *
69 * #include <net/if.h>
70 *
71 * void if_freenameindex(struct if_nameindex *ptr);
72 *
73 * The argument to this function must be a pointer that was returned by
74 * if_nameindex().
75 */
76
77struct if_nameindex *
78if_nameindex(void)
79{
80 struct ifaddrs *ifaddrs, *ifa;
81 unsigned int ni;
82 size_t nbytes;
83 struct if_nameindex *ifni, *ifni2;
84 char *cp;
85
86 if (getifaddrs(&ifaddrs) < 0)
87 return(NULL);
88
89 /*
90 * First, find out how many interfaces there are, and how
91 * much space we need for the string names.
92 */
93 ni = 0;
94 nbytes = 0;
95 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
96 if (ifa->ifa_addr &&
97 ifa->ifa_addr->sa_family == AF_LINK) {
98 nbytes += strlen(ifa->ifa_name) + 1;
99 ni++;
100 }
101 }
102
103 /*
104 * Next, allocate a chunk of memory, use the first part
105 * for the array of structures, and the last part for
106 * the strings.
107 */
108 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
109 ifni = (struct if_nameindex *)cp;
110 if (ifni == NULL)
111 goto out;
112 cp += (ni + 1) * sizeof(struct if_nameindex);
113
114 /*
115 * Now just loop through the list of interfaces again,
116 * filling in the if_nameindex array and making copies
117 * of all the strings.
118 */
119 ifni2 = ifni;
120 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
121 if (ifa->ifa_addr &&
122 ifa->ifa_addr->sa_family == AF_LINK) {
123 ifni2->if_index =
124 ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
125 ifni2->if_name = cp;
126 nbytes = strlen(ifa->ifa_name) + 1;
127 memcpy(cp, ifa->ifa_name, nbytes);
128 ifni2++;
129 cp += nbytes;
130 }
131 }
132 /*
133 * Finally, don't forget to terminate the array.
134 */
135 ifni2->if_index = 0;
136 ifni2->if_name = NULL;
137out:
138 freeifaddrs(ifaddrs);
139 return(ifni);
140}
diff --git a/src/lib/libc/net/if_nametoindex.c b/src/lib/libc/net/if_nametoindex.c
new file mode 100644
index 0000000000..8bd792b949
--- /dev/null
+++ b/src/lib/libc/net/if_nametoindex.c
@@ -0,0 +1,81 @@
1/* $OpenBSD: if_nametoindex.c,v 1.8 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nametoindex.c,v 1.5 2000/11/24 08:04:40 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. 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 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <net/if_dl.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2553:
40 *
41 * 4.1 Name-to-Index
42 *
43 *
44 * The first function maps an interface name into its corresponding
45 * index.
46 *
47 * #include <net/if.h>
48 *
49 * unsigned int if_nametoindex(const char *ifname);
50 *
51 * If the specified interface name does not exist, the return value is
52 * 0, and errno is set to ENXIO. If there was a system error (such as
53 * running out of memory), the return value is 0 and errno is set to the
54 * proper value (e.g., ENOMEM).
55 */
56
57unsigned int
58if_nametoindex(const char *ifname)
59{
60 struct ifaddrs *ifaddrs, *ifa;
61 unsigned int ni;
62
63 if (getifaddrs(&ifaddrs) < 0)
64 return(0);
65
66 ni = 0;
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 strcmp(ifa->ifa_name, ifname) == 0) {
72 ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
73 break;
74 }
75 }
76
77 freeifaddrs(ifaddrs);
78 if (!ni)
79 errno = ENXIO;
80 return(ni);
81}
diff --git a/src/lib/libc/net/inet.3 b/src/lib/libc/net/inet.3
new file mode 100644
index 0000000000..43cb5bafd7
--- /dev/null
+++ b/src/lib/libc/net/inet.3
@@ -0,0 +1,355 @@
1.\" $OpenBSD: inet.3,v 1.18 2003/09/09 12:00:39 jmc Exp $
2.\" $NetBSD: inet.3,v 1.7 1997/06/18 02:25:24 lukem Exp $
3.\"
4.\" Copyright (c) 1983, 1990, 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.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
32.\"
33.Dd June 18, 1997
34.Dt INET 3
35.Os
36.Sh NAME
37.Nm inet_addr ,
38.Nm inet_aton ,
39.Nm inet_lnaof ,
40.Nm inet_makeaddr ,
41.Nm inet_netof ,
42.Nm inet_network ,
43.Nm inet_ntoa ,
44.Nm inet_ntop ,
45.Nm inet_pton
46.Nd Internet address manipulation routines
47.Sh SYNOPSIS
48.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h>
50.Fd #include <netinet/in.h>
51.Fd #include <arpa/inet.h>
52.Ft in_addr_t
53.Fn inet_addr "const char *cp"
54.Ft int
55.Fn inet_aton "const char *cp" "struct in_addr *addr"
56.Ft in_addr_t
57.Fn inet_lnaof "struct in_addr in"
58.Ft struct in_addr
59.Fn inet_makeaddr "in_addr_t net" "in_addr_t lna"
60.Ft in_addr_t
61.Fn inet_netof "struct in_addr in"
62.Ft in_addr_t
63.Fn inet_network "const char *cp"
64.Ft char *
65.Fn inet_ntoa "struct in_addr in"
66.Ft const char *
67.Fn inet_ntop "int af" "const void *src" "char *dst" "size_t size"
68.Ft int
69.Fn inet_pton "int af" "const char *src" "void *dst"
70.Sh DESCRIPTION
71The routines
72.Fn inet_aton ,
73.Fn inet_addr
74and
75.Fn inet_network
76interpret character strings representing
77numbers expressed in the Internet standard
78.Ql \&.
79notation.
80The
81.Fn inet_pton
82function converts a presentation format address (that is, printable form
83as held in a character string) to network format (usually a
84.Li struct in_addr
85or some other internal binary representation, in network byte order).
86It returns 1 if the address was valid for the specified address family, or
870 if the address wasn't parseable in the specified address family, or \-1
88if some system error occurred (in which case
89.Va errno
90will have been set).
91This function is presently valid for
92.Dv AF_INET
93and
94.Dv AF_INET6 .
95The
96.Fn inet_aton
97routine interprets the specified character string as an Internet address,
98placing the address into the structure provided.
99It returns 1 if the string was successfully interpreted,
100or 0 if the string was invalid.
101The
102.Fn inet_addr
103and
104.Fn inet_network
105functions return numbers suitable for use
106as Internet addresses and Internet network
107numbers, respectively.
108.Pp
109The function
110.Fn inet_ntop
111converts an address from network format (usually a
112.Li struct in_addr
113or some other binary form, in network byte order) to presentation format
114(suitable for external display purposes).
115It returns
116.Dv NULL
117if a system
118error occurs (in which case,
119.Va errno
120will have been set), or it returns a pointer to the destination string.
121The routine
122.Fn inet_ntoa
123takes an Internet address and returns an
124.Tn ASCII
125string representing the address in
126.Ql \&.
127notation.
128The routine
129.Fn inet_makeaddr
130takes an Internet network number and a local
131network address and constructs an Internet address
132from it.
133The routines
134.Fn inet_netof
135and
136.Fn inet_lnaof
137break apart Internet host addresses, returning
138the network number and local network address part,
139respectively.
140.Pp
141All Internet addresses are returned in network
142order (bytes ordered from left to right).
143All network numbers and local address parts are
144returned as machine format integer values.
145.Sh INTERNET ADDRESSES (IP VERSION 4)
146Values specified using the
147.Ql \&.
148notation take one
149of the following forms:
150.Bd -literal -offset indent
151a.b.c.d
152a.b.c
153a.b
154a
155.Ed
156.Pp
157When four parts are specified, each is interpreted
158as a byte of data and assigned, from left to right,
159to the four bytes of an Internet address.
160Note that when an Internet address is viewed as a 32-bit
161integer quantity on a system that uses little-endian
162byte order (such as the
163.Tn Intel 386, 486
164and
165.Tn Pentium
166processors) the bytes referred to above appear as
167.Dq Li d.c.b.a .
168That is, little-endian bytes are ordered from right to left.
169.Pp
170When a three part address is specified, the last
171part is interpreted as a 16-bit quantity and placed
172in the rightmost two bytes of the network address.
173This makes the three part address format convenient
174for specifying Class B network addresses as
175.Dq Li 128.net.host .
176.Pp
177When a two part address is supplied, the last part
178is interpreted as a 24-bit quantity and placed in
179the rightmost three bytes of the network address.
180This makes the two part address format convenient
181for specifying Class A network addresses as
182.Dq Li net.host .
183.Pp
184When only one part is given, the value is stored
185directly in the network address without any byte
186rearrangement.
187.Pp
188All numbers supplied as
189.Dq parts
190in a
191.Ql \&.
192notation
193may be decimal, octal, or hexadecimal, as specified
194in the C language (i.e., a leading 0x or 0X implies
195hexadecimal; otherwise, a leading 0 implies octal;
196otherwise, the number is interpreted as decimal).
197.Sh INTERNET ADDRESSES (IP VERSION 6)
198In order to support scoped IPv6 addresses,
199.Xr getaddrinfo 3
200and
201.Xr getnameinfo 3
202are recommended rather than the functions presented here.
203.Pp
204The presentation format of an IPv6 address is given in RFC 2373:
205.Pp
206There are three conventional forms for representing IPv6 addresses as
207text strings:
208.Bl -enum
209.It
210The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
211hexadecimal values of the eight 16-bit pieces of the address.
212Examples:
213.Bd -literal -offset indent
214FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2151080:0:0:0:8:800:200C:417A
216.Ed
217.Pp
218Note that it is not necessary to write the leading zeros in an
219individual field, but there must be at least one numeral in
220every field (except for the case described in 2.).
221.It
222Due to the method of allocating certain styles of IPv6
223addresses, it will be common for addresses to contain long
224strings of zero bits.
225In order to make writing addresses
226containing zero bits easier, a special syntax is available to
227compress the zeros.
228The use of
229.Dq \&:\&:
230indicates multiple groups
231of 16 bits of zeros.
232The
233.Dq \&:\&:
234can only appear once in an
235address.
236The
237.Dq \&:\&:
238can also be used to compress the leading and/or trailing zeros in an address.
239.Pp
240For example the following addresses:
241.Bd -literal -offset indent
2421080:0:0:0:8:800:200C:417A a unicast address
243FF01:0:0:0:0:0:0:43 a multicast address
2440:0:0:0:0:0:0:1 the loopback address
2450:0:0:0:0:0:0:0 the unspecified addresses
246.Ed
247.Pp
248may be represented as:
249.Bd -literal -offset indent
2501080::8:800:200C:417A a unicast address
251FF01::43 a multicast address
252::1 the loopback address
253:: the unspecified addresses
254.Ed
255.It
256An alternative form that is sometimes more convenient when
257dealing with a mixed environment of IPv4 and IPv6 nodes is
258x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
259of the six high-order 16-bit pieces of the address, and the 'd's
260are the decimal values of the four low-order 8-bit pieces of the
261address (standard IPv4 representation).
262Examples:
263.Bd -literal -offset indent
2640:0:0:0:0:0:13.1.68.3
2650:0:0:0:0:FFFF:129.144.52.38
266.Ed
267.Pp
268or in compressed form:
269.Bd -literal -offset indent
270::13.1.68.3
271::FFFF:129.144.52.38
272.Ed
273.El
274.Sh DIAGNOSTICS
275The constant
276.Dv INADDR_NONE
277is returned by
278.Fn inet_addr
279and
280.Fn inet_network
281for malformed requests.
282.Sh SEE ALSO
283.Xr byteorder 3 ,
284.Xr gethostbyname 3 ,
285.Xr getnetent 3 ,
286.Xr inet_net 3 ,
287.Xr hosts 5 ,
288.Xr networks 5
289.Rs
290.%R RFC 2373
291.%D July 1998
292.%T "IP Version 6 Addressing Architecture"
293.Re
294.Rs
295.%R RFC 3493
296.%D February 2003
297.%T "Basic Socket Interface Extensions for IPv6"
298.Re
299.Sh STANDARDS
300The
301.Nm inet_ntop
302and
303.Nm inet_pton
304functions conform to the IETF IPv6 BSD API and address formatting
305specifications.
306Note that
307.Nm inet_pton
308does not accept 1-, 2-, or 3-part dotted addresses; all four parts
309must be specified.
310This is a narrower input set than that accepted by
311.Nm inet_aton .
312.Sh HISTORY
313The
314.Nm inet_addr ,
315.Nm inet_network ,
316.Nm inet_makeaddr ,
317.Nm inet_lnaof
318and
319.Nm inet_netof
320functions appeared in
321.Bx 4.2 .
322The
323.Nm inet_aton
324and
325.Nm inet_ntoa
326functions appeared in
327.Bx 4.3 .
328The
329.Nm inet_pton
330and
331.Nm inet_ntop
332functions appeared in BIND 4.9.4.
333.Sh BUGS
334The value
335.Dv INADDR_NONE
336(0xffffffff) is a valid broadcast address, but
337.Fn inet_addr
338cannot return that value without indicating failure.
339Also,
340.Fn inet_addr
341should have been designed to return a
342.Li struct in_addr .
343The newer
344.Fn inet_aton
345function does not share these problems, and almost all existing code
346should be modified to use
347.Fn inet_aton
348instead.
349.Pp
350The problem of host byte ordering versus network byte ordering is
351confusing.
352.Pp
353The string returned by
354.Fn inet_ntoa
355resides in a static memory area.
diff --git a/src/lib/libc/net/inet6_option_space.3 b/src/lib/libc/net/inet6_option_space.3
new file mode 100644
index 0000000000..5beec487ac
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,438 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.18 2005/01/11 17:45:41 jaredy Exp $
2.\" $KAME: inet6_option_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\"
4.\" Copyright (C) 2004 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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.Dd December 23, 2004
32.Dt INET6_OPTION_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_option_space ,
37.Nm inet6_option_init ,
38.Nm inet6_option_append ,
39.Nm inet6_option_alloc ,
40.Nm inet6_option_next ,
41.Nm inet6_option_find
42.Nd IPv6 Hop-by-Hop and Destination Option Manipulation
43.\"
44.Sh SYNOPSIS
45.In sys/types.h
46.In netinet/in.h
47.Ft "int"
48.Fn inet6_option_space "int nbytes"
49.Ft "int"
50.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
51.Ft "int"
52.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
53.Ft "u_int8_t *"
54.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy"
55.Ft "int"
56.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
57.Ft "int"
58.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
59.\"
60.Sh DESCRIPTION
61.\"
62Manipulating and parsing IPv6's Hop-by-Hop and Destination options is
63complicated by the need to properly align and pad data as well as the
64need to manipulate ancillary information that is not part of the data
65stream.
66RFC 2292 defines a set of functions, which are implemented as
67part of the Kame libraries, to help developers create, change,
68and parse Hop-by-Hop and Destination options.
69All of the prototypes
70for the option functions are defined in the
71.Aq Pa netinet/in.h
72header file.
73.\"
74.Ss inet6_option_space
75In order to determine the amount of space necessary to hold any option
76the
77.Fn inet6_option_space
78function is called.
79It returns the number of bytes required to hold
80an option when it is stored as ancillary data, including the
81.Li cmsghdr
82structure at the beginning, and any necessary padding at the end.
83The
84.Fa nbytes
85argument indicates the size of the structure defining the option,
86and must include any pad bytes at the beginning (the value
87.Li y
88in the alignment term
89.Dq Li "xn + y" ) ,
90the type byte, the length byte, and the option data.
91.Pp
92Note: If multiple options are stored in a single ancillary data
93object, which is the recommended technique, the
94.Fn inet6_option_space
95function overestimates the amount of space required by the size of
96.Li N-1
97.Li cmsghdr
98structures, where
99.Li N
100is the number of options to be stored in the object.
101Usually this has
102no impact because it is assumed that most Hop-by-Hop and Destination
103option headers carry only one option as indicated in appendix B of RFC 2460.
104.\"
105.Ss inet6_option_init
106The
107.Fn inet6_option_init
108function is called to initialize any ancillary data object that will contain
109a Hop-by-Hop or Destination option.
110It returns
111.Li 0
112on success and
113.Li \-1
114when an error occurs.
115.Pp
116The
117.Fa bp
118argument points to a previously allocated area of memory which must be
119large enough to contain all the arguments that the application intends
120to add later via the
121.Fn inet6_option_append
122and
123.Fn inet6_option_alloc
124routines.
125.Pp
126The
127.Fa cmsgp
128argument is a pointer to a pointer to a
129.Li cmsghdr
130structure.
131The
132.Fa *cmsgp
133argument
134points to a
135.Li cmsghdr
136structure which is constructed by this function and stored in the
137area of memory pointed to by
138.Fa bp .
139.Pp
140The
141.Fa type
142is either
143.Dv IPV6_HOPOPTS
144or
145.Dv IPV6_DSTOPTS
146and is stored in the
147.Li cmsg_type
148member of the
149.Li cmsghdr
150structure mentioned above.
151.\"
152.Ss inet6_option_append
153This function appends a Hop-by-Hop option or a Destination option into
154an ancillary data object previously initialized by a call to
155.Fn inet6_option_init .
156The
157.Fn inet6_option_append
158function returns
159.Li 0
160if it succeeds or
161.Li \-1
162when an error occurs.
163.Pp
164The
165.Fa cmsg
166argument is a pointer to the
167.Li cmsghdr
168structure that was initialized by a call to
169.Fn inet6_option_init .
170.Pp
171The
172.Fa typep
173argument is a pointer to the 8-bit option type.
174All options are
175encoded as type-length-value tuples and it is assumed that
176the
177.Fa typep
178field is immediately followed by the 8-bit option data length field,
179which is then followed by the option data.
180.Pp
181The option types of
182.Li 0
183and
184.Li 1
185are reserved for the
186.Li Pad1
187and
188.Li PadN
189options respectively.
190All other values from
191.Li 2
192through
193.Li 255
194are available for applications to use.
195.Pp
196The option data length, since it is stored in 8 bites, must have a
197value between
198.Li 0
199and
200.Li 255 ,
201inclusive.
202.Pp
203The
204.Fa multx
205argument
206is the value
207.Li x
208in the alignment term
209.Dq Li xn + y
210and indicates the byte alignment necessary for the data.
211Alignments may be specified as
212.Li 1 ,
213.Li 2 ,
214.Li 4 ,
215or
216.Li 8
217bytes, which is no alignment, 16-bit, 32-bit and 64-bit alignments
218respectively.
219.Pp
220The
221.Fa plusy
222argument
223is the value
224.Li y
225in the alignment term
226.Dq Li xn + y
227and must have a value between
228.Li 0
229and
230.Li 7 ,
231inclusive, indicating the amount of padding that is necessary for an
232option.
233.\"
234.Ss inet6_option_alloc
235The
236.Fn inet6_option_alloc
237function appends a Hop-by-Hop option or a Destination option into an
238ancillary data object that has previously been initialized by a call to
239.Fn inet6_option_init .
240A successful call to the
241.Fn inet6_option_alloc
242function returns a pointer to the 8-bit option type field,
243which is at the beginning of the allocated region.
244.Fn inet6_option_alloc
245returns
246.Dv NULL
247when an error has occurred.
248.Pp
249The difference between the
250.Fn inet6_option_alloc
251and
252.Fn inet6_option_append
253functions is that the latter copies the contents of a previously built
254option into the ancillary data object while the former returns a
255pointer to the place in the data object where the option's TLV must
256then be built by the application.
257.Pp
258The
259.Fa cmsg
260argument is a pointer to a
261.Li cmsghdr
262structure that was initialized by
263.Fn inet6_option_init .
264.Pp
265The
266.Fa datalen
267argument is the value of the option data length byte for this option.
268This value is required as an argument to allow the function to
269determine if padding must be appended at the end of the option.
270(The
271.Fn inet6_option_append
272function does not need a data length argument
273since the option data length must already be stored by the caller.)
274.Pp
275The
276.Fa multx
277and
278.Fa plusy
279arguments
280are identical to the arguments of the same name described in the
281.Fn inet6_option_init
282function above.
283.\"
284.Ss inet6_option_next
285The
286.Fn inet6_option_next
287function is used to process Hop-by-Hop and Destination options that
288are present in an ancillary data object.
289When an option remains to
290be processed, the return value of the
291.Fn inet6_option_next
292function is
293.Li 0
294and the
295.Fa *tptrp
296argument points to the 8-bit option type field, which is followed by
297the 8-bit option data length, and then the option data.
298When no more
299options remain to be processed, the return value is
300.Li \-1
301and
302.Fa *tptrp
303is
304.Dv NULL .
305When an error occurs, the return value is
306.Li \-1 ,
307but the
308.Fa *tptrp
309argument is not
310.Dv NULL .
311This set of return values allows a program to easily loop through all
312the options in an ancillary data object, checking for the error and
313end of stream conditions along the way.
314.Pp
315When a valid option is returned, the
316.Fa cmsg
317argument points to a
318.Li cmsghdr
319where the
320.Li cmsg_level
321element equals
322.Dv IPPROTO_IPV6
323and the
324.Li cmsg_type
325element is either
326.Dv IPV6_HOPOPTS
327or
328.Dv IPV6_DSTOPTS .
329.Pp
330The
331.Fa tptrp
332argument is a pointer to a pointer to an 8-bit byte and
333.Fa *tptrp
334is used by the function to remember its place in the ancillary data
335object each time the function is called.
336When the
337.Fn inet6_option_next
338function is called for the first time on a given ancillary data object,
339.Fa *tptrp
340must be set to
341.Dv NULL .
342.Pp
343Each time the function returns success,
344the
345.Fa *tptrp
346argument points to the 8-bit option type field for the next option to
347be processed.
348.\"
349.Ss inet6_option_find
350The
351.Fn inet6_option_find
352function allows an application to search for a particular option type
353in an ancillary data object.
354The
355.Fa cmsg
356argument is a pointer to a
357.Li cmsghdr
358structure in which the
359.Li cmsg_level
360element equals
361.Dv IPPROTO_IPV6
362and the
363.Li cmsg_type
364element is either
365.Dv IPV6_HOPOPTS
366or
367.Dv IPV6_DSTOPTS .
368.Pp
369The
370.Fa tptrp
371argument is handled exactly as in the
372.Fn inet6_option_next
373function described above.
374.Pp
375The
376.Fn inet6_option_find
377function starts searching for an option of the specified type
378beginning after the value of
379.Fa *tptrp .
380.\"
381.Sh EXAMPLES
382RFC 2292 gives comprehensive examples in chapter 6.
383.\"
384.Sh DIAGNOSTICS
385The
386.Fn inet6_option_init
387and
388.Fn inet6_option_append
389functions return
390.Li 0
391on success or
392.Li \-1
393on an error.
394.Pp
395The
396.Fn inet6_option_alloc
397function returns
398.Dv NULL
399on an error.
400.Pp
401When
402.Fn inet6_option_next
403or
404.Fn inet6_option_find
405detect an error they return
406.Li \-1 ,
407setting
408.Fa *tptrp
409to a non
410.Dv NULL
411value.
412.\"
413.Sh SEE ALSO
414.Xr inet6 4 ,
415.Xr ip6 4
416.Rs
417.%A W. Stevens
418.%A M. Thomas
419.%T "Advanced Sockets API for IPv6"
420.%N RFC 2292
421.%D February 1998
422.Re
423.Rs
424.%A S. Deering
425.%A R. Hinden
426.%T "Internet Protocol, Version 6 (IPv6) Specification"
427.%N RFC 2460
428.%D December 1998
429.Re
430.\"
431.Sh STANDARDS
432The functions are documented in
433.Dq Advanced Sockets API for IPv6
434(RFC 2292).
435.\"
436.Sh HISTORY
437This implementation first appeared in the KAME advanced networking kit.
438.\"
diff --git a/src/lib/libc/net/inet6_rthdr_space.3 b/src/lib/libc/net/inet6_rthdr_space.3
new file mode 100644
index 0000000000..7c00c42e42
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,308 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.17 2005/01/11 17:45:41 jaredy Exp $
2.\" $KAME: inet6_rthdr_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\"
4.\" Copyright (C) 2004 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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.Dd December 27, 2004
32.Dt INET6_RTHDR_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_rthdr_space ,
37.Nm inet6_rthdr_init ,
38.Nm inet6_rthdr_add ,
39.Nm inet6_rthdr_lasthop ,
40.Nm inet6_rthdr_reverse ,
41.Nm inet6_rthdr_segments ,
42.Nm inet6_rthdr_getaddr ,
43.Nm inet6_rthdr_getflags
44.Nd IPv6 Routing Header Options Manipulation
45.\"
46.Sh SYNOPSIS
47.In sys/types.h
48.In netinet/in.h
49.Ft size_t
50.Fn inet6_rthdr_space "int type" "int segments"
51.Ft "struct cmsghdr *"
52.Fn inet6_rthdr_init "void *bp" "int type"
53.Ft int
54.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
55.Ft int
56.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
57.Ft int
58.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
59.Ft int
60.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
61.Ft "struct in6_addr *"
62.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
63.Ft int
64.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
65.\"
66.Sh DESCRIPTION
67.\"The RFC 2292 IPv6 Advanced API has been deprecated in favor of the
68.\"newer, RFC 3542 APIs.
69.\"On platforms that support it, currently only
70.\"FreeBSD, please use the newer API to manipulate routing header
71.\"options.
72.\".Pp
73The RFC 2292 IPv6 Advanced API defined eight functions for
74applications to use for building and parsing routing headers.
75The
76eight functions are split into two groups, the first of which builds
77the header and the second of which can parse it.
78The function prototypes for these functions are all in the
79.Aq Pa netinet/in.h
80header.
81Although direct manipulation of a routing header is possible,
82this set of APIs make it unnecessary and such direct manipulation
83should be avoided so that changes to the underlying structures do not
84break applications.
85.Pp
86Please note that RFC 2292 uses the term
87.Dq segments
88instead of the term
89.Dq addresses
90but they are considered equivalent for this manual page.
91.\"
92.Ss inet6_rthdr_space
93The
94.Fn inet6_rthdr_space
95function returns the number of bytes required to hold a routing header
96of the specified
97.Fa type
98and containing the specified number of
99.Fa segments .
100Only one
101.Fa type
102is supported,
103.Dv IPV6_RTHDR_TYPE_0 ,
104and it can hold from 1 to 23 segments.
105The return value includes the
106size of the
107.Vt cmsghdr
108structure that precedes the routing header and
109any required padding.
110.Pp
111A return value of 0 indicates an error.
112Either the type was specified
113incorrectly, or the number of segments was less than one or greater
114than 23.
115.Pp
116Note: The
117.Fn inet6_rthdr_space
118function only returns the size required by the routing header and does
119not allocate memory for the caller.
120.\"
121.Ss inet6_rthdr_init
122The
123.Fn inet6_rthdr_init
124function initializes a buffer, pointed to by
125.Fa bp
126with an appropriate
127.Li cmsghdr
128structure followed by a routing header of the specified
129.Fa type .
130.Pp
131The caller must use the
132.Fn inet6_rthdr_space
133function to determine the size of the buffer, and then allocate that
134buffer before calling
135.Fn inet6_rthdr_init .
136.Pp
137The return value is a pointer to a
138.Li cmsghdr
139structure, which is used as the first argument to the
140.Fn inet6_rthdr_add
141and
142.Fn inet6_rthdr_lasthop
143functions in order to construct the routing header.
144When an error occurs the return value is
145.Dv NULL .
146.\"
147.Ss inet6_rthdr_add
148The
149.Fn inet6_rthdr_add
150function adds the IPv6 address pointed to by
151.Fa addr
152to the end of the
153routing header being constructed and sets the type of this address to the
154value of
155.Fa flags .
156The
157.Fa flags
158must be either
159.Dv IPV6_RTHDR_LOOSE
160or
161.Dv IPV6_RTHDR_STRICT
162indicating whether loose or strict source routing is required.
163.Pp
164When the function succeeds it returns 0, otherwise \-1 is returned.
165.\"
166.Ss inet6_rthdr_lasthop
167The
168.Fn inet6_rthdr_lasthop
169function specifies the strict or loose flag for the final hop of a
170routing header.
171The
172.Fa flags
173argument must be either
174.Dv IPV6_RTHDR_LOOSE
175or
176.Dv IPV6_RTHDR_STRICT .
177.Pp
178The return value of the function is 0 upon success, and \-1 when an
179error has occurred.
180.Pp
181Please note that a routing header specifying
182.Li N
183intermediate nodes requires
184.Li N+1
185strict or loose flags meaning that
186.Fn inet6_rthdr_add
187must be called
188.Li N
189times and then
190.Fn inet6_rthdr_lasthop
191must be called once.
192.\"
193.Ss inet6_rthdr_reverse
194This function was never implemented.
195.Pp
196The following three functions provide an API for parsing a received
197routing header:
198.\"
199.Ss inet6_rthdr_segments
200The
201.Fn inet6_rthdr_segments
202function returns the number of segments contained in the routing
203header pointed to by the
204.Fa cmsg
205argument.
206On success the return value is from 1 to 23.
207When an error occurs, \-1 is returned.
208.\"
209.Ss inet6_rthdr_getaddr
210The
211.Fn inet6_rthdr_getaddr
212function returns a pointer to the IPv6 address specified by the
213.Fa index
214argument from the routing header pointed to by
215.Fa cmsg .
216The index must be between 1 and the number returned by
217.Fn inet6_rthdr_segments ,
218described above.
219An application must call
220.Fn inet6_rthdr_segments
221to obtain the number of segments in the routing header.
222.Pp
223If an error occurs,
224.Dv NULL
225is returned.
226.\"
227.Ss inet6_rthdr_getflags
228The
229.Fn inet6_rthdr_getflags
230function returns the flags value of the segment specified by
231.Fa index
232of the routing header pointed to by
233.Fa cmsg .
234The
235.Fa index
236argument must be between 0 and the value returned by
237.Fn inet6_rthdr_segments .
238The return value will be either
239.Dv IPV6_RTHDR_LOOSE
240or
241.Dv IPV6_RTHDR_STRICT
242indicating whether loose or strict source routing was requested for
243that segment.
244.Pp
245When an error occurs, \-1 is returned.
246.Pp
247Note: Flags begin at index 0 while segments begin at index 1, to
248maintain consistency with the terminology and figures in RFC 2460.
249.\"
250.Sh EXAMPLES
251RFC 2292 gives comprehensive examples in chapter 8.
252.\"
253.Sh DIAGNOSTICS
254The
255.Fn inet6_rthdr_space
256function returns 0 when an error occurs.
257.Pp
258The
259.Fn inet6_rthdr_add
260and
261.Fn inet6_rthdr_lasthop
262functions return 0 on success, and \-1 on error.
263.Pp
264The
265.Fn inet6_rthdr_init
266and
267.Fn inet6_rthdr_getaddr
268functions
269return
270.Dv NULL
271on error.
272.Pp
273The
274.Fn inet6_rthdr_segments
275and
276.Fn inet6_rthdr_getflags
277functions return \-1 on error.
278.\"
279.Sh SEE ALSO
280.Xr inet6 4 ,
281.Xr ip6 4
282.Rs
283.%A W. Stevens
284.%A M. Thomas
285.%T "Advanced Sockets API for IPv6"
286.%N RFC 2292
287.%D February 1998
288.Re
289.Rs
290.%A S. Deering
291.%A R. Hinden
292.%T "Internet Protocol, Version 6 (IPv6) Specification"
293.%N RFC 2460
294.%D December 1998
295.Re
296.\"
297.Sh HISTORY
298This implementation first appeared in the KAME advanced networking kit.
299.\"
300.Sh BUGS
301The
302.Fn inet6_rthdr_reverse
303function was never implemented.
304.\".Pp
305.\"This API is deprecated in favor of
306.\".Xr inet6_rth_space 3
307.\".Sh SEE ALSO
308.\".Xr inet6_rth_space 3
diff --git a/src/lib/libc/net/inet_addr.c b/src/lib/libc/net/inet_addr.c
new file mode 100644
index 0000000000..b55983fd81
--- /dev/null
+++ b/src/lib/libc/net/inet_addr.c
@@ -0,0 +1,180 @@
1/* $OpenBSD: inet_addr.c,v 1.8 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * ++Copyright++ 1983, 1990, 1993
5 * -
6 * Copyright (c) 1983, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
57static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.8 2005/03/25 13:24:12 otto Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <ctype.h>
68
69/*
70 * Ascii internet address interpretation routine.
71 * The value returned is in network order.
72 */
73in_addr_t
74inet_addr(const char *cp)
75{
76 struct in_addr val;
77
78 if (inet_aton(cp, &val))
79 return (val.s_addr);
80 return (INADDR_NONE);
81}
82
83/*
84 * Check whether "cp" is a valid ascii representation
85 * of an Internet address and convert to a binary address.
86 * Returns 1 if the address is valid, 0 if not.
87 * This replaces inet_addr, the return value from which
88 * cannot distinguish between failure and a local broadcast address.
89 */
90int
91inet_aton(const char *cp, struct in_addr *addr)
92{
93 in_addr_t val;
94 int base, n;
95 char c;
96 u_int parts[4];
97 u_int *pp = parts;
98
99 c = *cp;
100 for (;;) {
101 /*
102 * Collect number up to ``.''.
103 * Values are specified as for C:
104 * 0x=hex, 0=octal, isdigit=decimal.
105 */
106 if (!isdigit(c))
107 return (0);
108 val = 0; base = 10;
109 if (c == '0') {
110 c = *++cp;
111 if (c == 'x' || c == 'X')
112 base = 16, c = *++cp;
113 else
114 base = 8;
115 }
116 for (;;) {
117 if (isascii(c) && isdigit(c)) {
118 val = (val * base) + (c - '0');
119 c = *++cp;
120 } else if (base == 16 && isascii(c) && isxdigit(c)) {
121 val = (val << 4) |
122 (c + 10 - (islower(c) ? 'a' : 'A'));
123 c = *++cp;
124 } else
125 break;
126 }
127 if (c == '.') {
128 /*
129 * Internet format:
130 * a.b.c.d
131 * a.b.c (with c treated as 16 bits)
132 * a.b (with b treated as 24 bits)
133 */
134 if (pp >= parts + 3)
135 return (0);
136 *pp++ = val;
137 c = *++cp;
138 } else
139 break;
140 }
141 /*
142 * Check for trailing characters.
143 */
144 if (c != '\0' && (!isascii(c) || !isspace(c)))
145 return (0);
146 /*
147 * Concoct the address according to
148 * the number of parts specified.
149 */
150 n = pp - parts + 1;
151 switch (n) {
152
153 case 0:
154 return (0); /* initial nondigit */
155
156 case 1: /* a -- 32 bits */
157 break;
158
159 case 2: /* a.b -- 8.24 bits */
160 if ((val > 0xffffff) || (parts[0] > 0xff))
161 return (0);
162 val |= parts[0] << 24;
163 break;
164
165 case 3: /* a.b.c -- 8.8.16 bits */
166 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
167 return (0);
168 val |= (parts[0] << 24) | (parts[1] << 16);
169 break;
170
171 case 4: /* a.b.c.d -- 8.8.8.8 bits */
172 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
173 return (0);
174 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
175 break;
176 }
177 if (addr)
178 addr->s_addr = htonl(val);
179 return (1);
180}
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
new file mode 100644
index 0000000000..110828b2f6
--- /dev/null
+++ b/src/lib/libc/net/inet_lnaof.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_lnaof.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Return the local network address portion of an
40 * internet address; handles class a/b/c network
41 * number formats.
42 */
43in_addr_t
44inet_lnaof(struct in_addr in)
45{
46 in_addr_t i = ntohl(in.s_addr);
47
48 if (IN_CLASSA(i))
49 return ((i)&IN_CLASSA_HOST);
50 else if (IN_CLASSB(i))
51 return ((i)&IN_CLASSB_HOST);
52 else
53 return ((i)&IN_CLASSC_HOST);
54}
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
new file mode 100644
index 0000000000..9a15da8fec
--- /dev/null
+++ b/src/lib/libc/net/inet_makeaddr.c
@@ -0,0 +1,57 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_makeaddr.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Formulate an Internet address from network + host. Used in
40 * building addresses stored in the ifnet structure.
41 */
42struct in_addr
43inet_makeaddr(in_addr_t net, in_addr_t host)
44{
45 in_addr_t addr;
46
47 if (net < 128)
48 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
49 else if (net < 65536)
50 addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
51 else if (net < 16777216L)
52 addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
53 else
54 addr = net | host;
55 addr = htonl(addr);
56 return (*(struct in_addr *)&addr);
57}
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..c14fa52e38
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,181 @@
1.\" $OpenBSD: inet_net.3,v 1.10 2003/05/01 19:17:37 jmc Exp $
2.\" $NetBSD: inet_net.3,v 1.1 1997/06/18 02:25:27 lukem Exp $
3.\"
4.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Luke Mewburn.
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. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd June 18, 1997
39.Dt INET_NET 3
40.Os
41.Sh NAME
42.Nm inet_net_ntop ,
43.Nm inet_net_pton
44.Nd Internet network number manipulation routines
45.Sh SYNOPSIS
46.Fd #include <sys/socket.h>
47.Fd #include <netinet/in.h>
48.Fd #include <arpa/inet.h>
49.Ft char *
50.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
51.Ft int
52.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
53.Sh DESCRIPTION
54The
55.Fn inet_net_ntop
56function converts an Internet network number from network format (usually a
57.Li struct in_addr
58or some other binary form, in network byte order) to CIDR presentation format
59(suitable for external display purposes).
60.Fa bits
61is the number of bits in
62.Fa src
63that are the network number.
64It returns
65.Dv NULL
66if a system error occurs (in which case,
67.Va errno
68will have been set), or it returns a pointer to the destination string.
69.Pp
70The
71.Fn inet_net_pton
72function converts a presentation format Internet network number (that is,
73printable form as held in a character string) to network format (usually a
74.Li struct in_addr
75or some other internal binary representation, in network byte order).
76It returns the number of bits (either computed based on the class, or
77specified with /CIDR), or \-1 if a failure occurred
78(in which case
79.Va errno
80will have been set.
81It will be set to
82.Er ENOENT
83if the Internet network number was not valid).
84.Pp
85Caution:
86The
87.Fa dst
88field should be zeroed before calling
89.Fn inet_net_pton
90as the function will only fill the number of bytes necessary to
91encode the network number in network byte order.
92.Pp
93The only value for
94.Fa af
95currently supported is
96.Dv AF_INET .
97.Fa size
98is the size of the result buffer
99.Fa dst .
100.Sh NETWORK NUMBERS (IP VERSION 4)
101The external representation of Internet network numbers may be specified in
102one of the following forms:
103.Bd -literal -offset indent
104a
105a.b
106a.b.c
107a.b.c.d
108.Ed
109.Pp
110Any of the above four forms may have
111.Dq Li /bits
112appended where
113.Dq Li bits
114is in the range
115.Li 0-32
116and is used to explicitly specify the number of bits in the network address.
117When
118.Dq Li /bits
119is not specified the number of bits in the network address is calculated
120as the larger of the number of bits in the class to which the address
121belongs and the number of bits provided rounded up modulo 8.
122Examples:
123.Bl -tag -width 10.1.2.3/24
124.It Li 10
125an 8 bit network number (class A), value
126.Li 10.0.0.0 .
127.It Li 192
128a 24 bit network number (class C), value
129.Li 192.0.0.0 .
130.It Li 10.10
131a 16 bit network number, value
132.Li 10.10.0.0 .
133.It Li 10.1.2
134a 24 bit network number, value
135.Li 10.1.2.0 .
136.It Li 10.1.2.3
137a 32 bit network number, value
138.Li 10.1.2.3 .
139.It Li 10.1.2.3/24
140a 24 bit network number (explicit), value
141.Li 10.1.2.3 .
142.El
143.Pp
144Note that when the number of bits is specified using
145.Dq Li /bits
146notation, the value of the address still includes all bits suplied
147in the external representation, even those bits which are the host
148part of an internet address.
149Also, unlike
150.Xr inet_pton 3
151where the external representation is assumed to be an internet address, the
152external representation for
153.Fn inet_net_pton
154is assumed to be a network address.
155Thus
156.Dq Li 10.1
157is assumed to be
158.Dq Li 10.1.0.0
159not
160.Dq Li 10.0.0.1
161.Pp
162All numbers supplied as
163.Dq parts
164in a
165.Ql \&.
166notation
167may be decimal, octal, or hexadecimal, as specified
168in the C language (i.e., a leading 0x or 0X implies
169hexadecimal; otherwise, a leading 0 implies octal;
170otherwise, the number is interpreted as decimal).
171.Sh SEE ALSO
172.Xr byteorder 3 ,
173.Xr inet 3 ,
174.Xr inet_pton 3 ,
175.Xr networks 5
176.Sh HISTORY
177The
178.Nm inet_net_ntop
179and
180.Nm inet_net_pton
181functions first appeared in BIND 4.9.4.
diff --git a/src/lib/libc/net/inet_net_ntop.c b/src/lib/libc/net/inet_net_ntop.c
new file mode 100644
index 0000000000..38978f3ccf
--- /dev/null
+++ b/src/lib/libc/net/inet_net_ntop.c
@@ -0,0 +1,143 @@
1/* $OpenBSD: inet_net_ntop.c,v 1.5 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37
38static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
39
40/*
41 * char *
42 * inet_net_ntop(af, src, bits, dst, size)
43 * convert network number from network to presentation format.
44 * generates CIDR style result always.
45 * return:
46 * pointer to dst, or NULL if an error occurred (check errno).
47 * author:
48 * Paul Vixie (ISC), July 1996
49 */
50char *
51inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
52{
53 switch (af) {
54 case AF_INET:
55 return (inet_net_ntop_ipv4(src, bits, dst, size));
56 default:
57 errno = EAFNOSUPPORT;
58 return (NULL);
59 }
60}
61
62/*
63 * static char *
64 * inet_net_ntop_ipv4(src, bits, dst, size)
65 * convert IPv4 network number from network to presentation format.
66 * generates CIDR style result always.
67 * return:
68 * pointer to dst, or NULL if an error occurred (check errno).
69 * note:
70 * network byte order assumed. this means 192.5.5.240/28 has
71 * 0x11110000 in its fourth octet.
72 * author:
73 * Paul Vixie (ISC), July 1996
74 */
75static char *
76inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
77{
78 char *odst = dst;
79 u_int m;
80 int b;
81 char *ep;
82 int advance;
83
84 ep = dst + size;
85 if (ep <= dst)
86 goto emsgsize;
87
88 if (bits < 0 || bits > 32) {
89 errno = EINVAL;
90 return (NULL);
91 }
92 if (bits == 0) {
93 if (ep - dst < sizeof "0")
94 goto emsgsize;
95 *dst++ = '0';
96 *dst = '\0';
97 }
98
99 /* Format whole octets. */
100 for (b = bits / 8; b > 0; b--) {
101 if (ep - dst < sizeof "255.")
102 goto emsgsize;
103 advance = snprintf(dst, ep - dst, "%u", *src++);
104 if (advance <= 0 || advance >= ep - dst)
105 goto emsgsize;
106 dst += advance;
107 if (b > 1) {
108 if (dst + 1 >= ep)
109 goto emsgsize;
110 *dst++ = '.';
111 *dst = '\0';
112 }
113 }
114
115 /* Format partial octet. */
116 b = bits % 8;
117 if (b > 0) {
118 if (ep - dst < sizeof ".255")
119 goto emsgsize;
120 if (dst != odst)
121 if (dst + 1 >= ep)
122 goto emsgsize;
123 *dst++ = '.';
124 m = ((1 << b) - 1) << (8 - b);
125 advance = snprintf(dst, ep - dst, "%u", *src & m);
126 if (advance <= 0 || advance >= ep - dst)
127 goto emsgsize;
128 dst += advance;
129 }
130
131 /* Format CIDR /width. */
132 if (ep - dst < sizeof "/32")
133 goto emsgsize;
134 advance = snprintf(dst, ep - dst, "/%u", bits);
135 if (advance <= 0 || advance >= ep - dst)
136 goto emsgsize;
137 dst += advance;
138 return (odst);
139
140 emsgsize:
141 errno = EMSGSIZE;
142 return (NULL);
143}
diff --git a/src/lib/libc/net/inet_net_pton.c b/src/lib/libc/net/inet_net_pton.c
new file mode 100644
index 0000000000..e544ca7e28
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,199 @@
1/* $OpenBSD: inet_net_pton.c,v 1.4 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.4 2005/03/25 13:24:12 otto Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <assert.h>
34#include <ctype.h>
35#include <errno.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40static int inet_net_pton_ipv4(const char *, u_char *, size_t);
41
42/*
43 * static int
44 * inet_net_pton(af, src, dst, size)
45 * convert network number from presentation to network format.
46 * accepts hex octets, hex strings, decimal octets, and /CIDR.
47 * "size" is in bytes and describes "dst".
48 * return:
49 * number of bits, either imputed classfully or specified with /CIDR,
50 * or -1 if some failure occurred (check errno). ENOENT means it was
51 * not a valid network specification.
52 * author:
53 * Paul Vixie (ISC), June 1996
54 */
55int
56inet_net_pton(int af, const char *src, void *dst, size_t size)
57{
58 switch (af) {
59 case AF_INET:
60 return (inet_net_pton_ipv4(src, dst, size));
61 default:
62 errno = EAFNOSUPPORT;
63 return (-1);
64 }
65}
66
67/*
68 * static int
69 * inet_net_pton_ipv4(src, dst, size)
70 * convert IPv4 network number from presentation to network format.
71 * accepts hex octets, hex strings, decimal octets, and /CIDR.
72 * "size" is in bytes and describes "dst".
73 * return:
74 * number of bits, either imputed classfully or specified with /CIDR,
75 * or -1 if some failure occurred (check errno). ENOENT means it was
76 * not an IPv4 network specification.
77 * note:
78 * network byte order assumed. this means 192.5.5.240/28 has
79 * 0x11110000 in its fourth octet.
80 * author:
81 * Paul Vixie (ISC), June 1996
82 */
83static int
84inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
85{
86 static const char
87 xdigits[] = "0123456789abcdef",
88 digits[] = "0123456789";
89 int n, ch, tmp, dirty, bits;
90 const u_char *odst = dst;
91
92 ch = *src++;
93 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
94 && isascii(src[1]) && isxdigit(src[1])) {
95 /* Hexadecimal: Eat nybble string. */
96 if (size <= 0)
97 goto emsgsize;
98 *dst = 0, dirty = 0;
99 src++; /* skip x or X. */
100 while ((ch = *src++) != '\0' &&
101 isascii(ch) && isxdigit(ch)) {
102 if (isupper(ch))
103 ch = tolower(ch);
104 n = strchr(xdigits, ch) - xdigits;
105 assert(n >= 0 && n <= 15);
106 *dst |= n;
107 if (!dirty++)
108 *dst <<= 4;
109 else if (size-- > 0)
110 *++dst = 0, dirty = 0;
111 else
112 goto emsgsize;
113 }
114 if (dirty)
115 size--;
116 } else if (isascii(ch) && isdigit(ch)) {
117 /* Decimal: eat dotted digit string. */
118 for (;;) {
119 tmp = 0;
120 do {
121 n = strchr(digits, ch) - digits;
122 assert(n >= 0 && n <= 9);
123 tmp *= 10;
124 tmp += n;
125 if (tmp > 255)
126 goto enoent;
127 } while ((ch = *src++) != '\0' &&
128 isascii(ch) && isdigit(ch));
129 if (size-- <= 0)
130 goto emsgsize;
131 *dst++ = (u_char) tmp;
132 if (ch == '\0' || ch == '/')
133 break;
134 if (ch != '.')
135 goto enoent;
136 ch = *src++;
137 if (!isascii(ch) || !isdigit(ch))
138 goto enoent;
139 }
140 } else
141 goto enoent;
142
143 bits = -1;
144 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
145 /* CIDR width specifier. Nothing can follow it. */
146 ch = *src++; /* Skip over the /. */
147 bits = 0;
148 do {
149 n = strchr(digits, ch) - digits;
150 assert(n >= 0 && n <= 9);
151 bits *= 10;
152 bits += n;
153 } while ((ch = *src++) != '\0' &&
154 isascii(ch) && isdigit(ch));
155 if (ch != '\0')
156 goto enoent;
157 if (bits > 32)
158 goto emsgsize;
159 }
160
161 /* Firey death and destruction unless we prefetched EOS. */
162 if (ch != '\0')
163 goto enoent;
164
165 /* If nothing was written to the destination, we found no address. */
166 if (dst == odst)
167 goto enoent;
168 /* If no CIDR spec was given, infer width from net class. */
169 if (bits == -1) {
170 if (*odst >= 240) /* Class E */
171 bits = 32;
172 else if (*odst >= 224) /* Class D */
173 bits = 4;
174 else if (*odst >= 192) /* Class C */
175 bits = 24;
176 else if (*odst >= 128) /* Class B */
177 bits = 16;
178 else /* Class A */
179 bits = 8;
180 /* If imputed mask is narrower than specified octets, widen. */
181 if (bits < ((dst - odst) * 8))
182 bits = (dst - odst) * 8;
183 }
184 /* Extend network to cover the actual mask. */
185 while (bits > ((dst - odst) * 8)) {
186 if (size-- <= 0)
187 goto emsgsize;
188 *dst++ = '\0';
189 }
190 return (bits);
191
192 enoent:
193 errno = ENOENT;
194 return (-1);
195
196 emsgsize:
197 errno = EMSGSIZE;
198 return (-1);
199}
diff --git a/src/lib/libc/net/inet_neta.c b/src/lib/libc/net/inet_neta.c
new file mode 100644
index 0000000000..c9bb3c0464
--- /dev/null
+++ b/src/lib/libc/net/inet_neta.c
@@ -0,0 +1,84 @@
1/* $OpenBSD: inet_neta.c,v 1.6 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "$OpenBSD: inet_neta.c,v 1.6 2005/03/25 13:24:12 otto Exp $";
22#endif
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <netinet/in.h>
27#include <arpa/inet.h>
28
29#include <errno.h>
30#include <stdio.h>
31#include <string.h>
32
33/*
34 * char *
35 * inet_neta(src, dst, size)
36 * format an in_addr_t network number into presentation format.
37 * return:
38 * pointer to dst, or NULL if an error occurred (check errno).
39 * note:
40 * format of ``src'' is as for inet_network().
41 * author:
42 * Paul Vixie (ISC), July 1996
43 */
44char *
45inet_neta(in_addr_t src, char *dst, size_t size)
46{
47 char *odst = dst;
48 char *ep;
49 int advance;
50
51 if (src == 0x00000000) {
52 if (size < sizeof "0.0.0.0")
53 goto emsgsize;
54 strlcpy(dst, "0.0.0.0", size);
55 return dst;
56 }
57 ep = dst + size;
58 if (ep <= dst)
59 goto emsgsize;
60 while (src & 0xffffffff) {
61 u_char b = (src & 0xff000000) >> 24;
62
63 src <<= 8;
64 if (b || src) {
65 if (ep - dst < sizeof "255.")
66 goto emsgsize;
67 advance = snprintf(dst, ep - dst, "%u", b);
68 if (advance <= 0 || advance >= ep - dst)
69 goto emsgsize;
70 dst += advance;
71 if (src != 0L) {
72 if (dst + 1 >= ep)
73 goto emsgsize;
74 *dst++ = '.';
75 *dst = '\0';
76 }
77 }
78 }
79 return (odst);
80
81 emsgsize:
82 errno = EMSGSIZE;
83 return (NULL);
84}
diff --git a/src/lib/libc/net/inet_netof.c b/src/lib/libc/net/inet_netof.c
new file mode 100644
index 0000000000..83f346c5f5
--- /dev/null
+++ b/src/lib/libc/net/inet_netof.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_netof.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Return the network number from an internet
40 * address; handles class a/b/c network #'s.
41 */
42in_addr_t
43inet_netof(struct in_addr in)
44{
45 in_addr_t i = ntohl(in.s_addr);
46
47 if (IN_CLASSA(i))
48 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
49 else if (IN_CLASSB(i))
50 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
51 else
52 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
53}
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
new file mode 100644
index 0000000000..7a7956ec83
--- /dev/null
+++ b/src/lib/libc/net/inet_network.c
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_network.c,v 1.9 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <ctype.h>
38
39/*
40 * Internet network address interpretation routine.
41 * The library routines call this routine to interpret
42 * network numbers.
43 */
44in_addr_t
45inet_network(const char *cp)
46{
47 in_addr_t val, base, n;
48 char c;
49 in_addr_t parts[4], *pp = parts;
50 int i;
51
52again:
53 val = 0; base = 10;
54 if (*cp == '0')
55 base = 8, cp++;
56 if (*cp == 'x' || *cp == 'X')
57 base = 16, cp++;
58 while ((c = *cp)) {
59 if (isdigit(c)) {
60 val = (val * base) + (c - '0');
61 cp++;
62 continue;
63 }
64 if (base == 16 && isxdigit(c)) {
65 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
66 cp++;
67 continue;
68 }
69 break;
70 }
71 if (*cp == '.') {
72 if (pp >= parts + 3)
73 return (INADDR_NONE);
74 *pp++ = val, cp++;
75 goto again;
76 }
77 if (*cp && !isspace(*cp))
78 return (INADDR_NONE);
79 *pp++ = val;
80 n = pp - parts;
81 for (val = 0, i = 0; i < 4; i++) {
82 val <<= 8;
83 if (i < n)
84 val |= parts[i] & 0xff;
85 }
86 return (val);
87}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
new file mode 100644
index 0000000000..0e7fe863f6
--- /dev/null
+++ b/src/lib/libc/net/inet_ntoa.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34/*
35 * Convert network-format internet address
36 * to base 256 d.d.d.d representation.
37 */
38#include <sys/types.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41#include <stdio.h>
42
43char *
44inet_ntoa(struct in_addr in)
45{
46 static char b[18];
47 char *p;
48
49 p = (char *)&in;
50#define UC(b) (((int)b)&0xff)
51 (void)snprintf(b, sizeof(b),
52 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
53 return (b);
54}
diff --git a/src/lib/libc/net/inet_ntop.c b/src/lib/libc/net/inet_ntop.c
new file mode 100644
index 0000000000..ec5c12983a
--- /dev/null
+++ b/src/lib/libc/net/inet_ntop.c
@@ -0,0 +1,203 @@
1/* $OpenBSD: inet_ntop.c,v 1.6 2005/03/25 13:24:12 otto Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.6 2005/03/25 13:24:12 otto Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35#include <stdio.h>
36
37/*
38 * WARNING: Don't even consider trying to compile this on a system where
39 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
40 */
41
42static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
43static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
44
45/* char *
46 * inet_ntop(af, src, dst, size)
47 * convert a network format address to presentation format.
48 * return:
49 * pointer to presentation format address (`dst'), or NULL (see errno).
50 * author:
51 * Paul Vixie, 1996.
52 */
53const char *
54inet_ntop(int af, const void *src, char *dst, size_t size)
55{
56 switch (af) {
57 case AF_INET:
58 return (inet_ntop4(src, dst, size));
59 case AF_INET6:
60 return (inet_ntop6(src, dst, size));
61 default:
62 errno = EAFNOSUPPORT;
63 return (NULL);
64 }
65 /* NOTREACHED */
66}
67
68/* const char *
69 * inet_ntop4(src, dst, size)
70 * format an IPv4 address, more or less like inet_ntoa()
71 * return:
72 * `dst' (as a const)
73 * notes:
74 * (1) uses no statics
75 * (2) takes a u_char* not an in_addr as input
76 * author:
77 * Paul Vixie, 1996.
78 */
79static const char *
80inet_ntop4(const u_char *src, char *dst, size_t size)
81{
82 static const char fmt[] = "%u.%u.%u.%u";
83 char tmp[sizeof "255.255.255.255"];
84 int l;
85
86 l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
87 if (l <= 0 || l >= size) {
88 errno = ENOSPC;
89 return (NULL);
90 }
91 strlcpy(dst, tmp, size);
92 return (dst);
93}
94
95/* const char *
96 * inet_ntop6(src, dst, size)
97 * convert IPv6 binary address into presentation (printable) format
98 * author:
99 * Paul Vixie, 1996.
100 */
101static const char *
102inet_ntop6(const u_char *src, char *dst, size_t size)
103{
104 /*
105 * Note that int32_t and int16_t need only be "at least" large enough
106 * to contain a value of the specified size. On some systems, like
107 * Crays, there is no such thing as an integer variable with 16 bits.
108 * Keep this in mind if you think this function should have been coded
109 * to use pointer overlays. All the world's not a VAX.
110 */
111 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
112 char *tp, *ep;
113 struct { int base, len; } best, cur;
114 u_int words[IN6ADDRSZ / INT16SZ];
115 int i;
116 int advance;
117
118 /*
119 * Preprocess:
120 * Copy the input (bytewise) array into a wordwise array.
121 * Find the longest run of 0x00's in src[] for :: shorthanding.
122 */
123 memset(words, '\0', sizeof words);
124 for (i = 0; i < IN6ADDRSZ; i++)
125 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
126 best.base = -1;
127 cur.base = -1;
128 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
129 if (words[i] == 0) {
130 if (cur.base == -1)
131 cur.base = i, cur.len = 1;
132 else
133 cur.len++;
134 } else {
135 if (cur.base != -1) {
136 if (best.base == -1 || cur.len > best.len)
137 best = cur;
138 cur.base = -1;
139 }
140 }
141 }
142 if (cur.base != -1) {
143 if (best.base == -1 || cur.len > best.len)
144 best = cur;
145 }
146 if (best.base != -1 && best.len < 2)
147 best.base = -1;
148
149 /*
150 * Format the result.
151 */
152 tp = tmp;
153 ep = tmp + sizeof(tmp);
154 for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
155 /* Are we inside the best run of 0x00's? */
156 if (best.base != -1 && i >= best.base &&
157 i < (best.base + best.len)) {
158 if (i == best.base) {
159 if (tp + 1 >= ep)
160 return (NULL);
161 *tp++ = ':';
162 }
163 continue;
164 }
165 /* Are we following an initial run of 0x00s or any real hex? */
166 if (i != 0) {
167 if (tp + 1 >= ep)
168 return (NULL);
169 *tp++ = ':';
170 }
171 /* Is this address an encapsulated IPv4? */
172 if (i == 6 && best.base == 0 &&
173 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
174 if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
175 return (NULL);
176 tp += strlen(tp);
177 break;
178 }
179 advance = snprintf(tp, ep - tp, "%x", words[i]);
180 if (advance <= 0 || advance >= ep - tp)
181 return (NULL);
182 tp += advance;
183 }
184 /* Was it a trailing run of 0x00's? */
185 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
186 if (tp + 1 >= ep)
187 return (NULL);
188 *tp++ = ':';
189 }
190 if (tp + 1 >= ep)
191 return (NULL);
192 *tp++ = '\0';
193
194 /*
195 * Check for overflow, copy, and we're done.
196 */
197 if ((size_t)(tp - tmp) > size) {
198 errno = ENOSPC;
199 return (NULL);
200 }
201 strlcpy(dst, tmp, size);
202 return (dst);
203}
diff --git a/src/lib/libc/net/inet_pton.c b/src/lib/libc/net/inet_pton.c
new file mode 100644
index 0000000000..ec158d4599
--- /dev/null
+++ b/src/lib/libc/net/inet_pton.c
@@ -0,0 +1,215 @@
1/* $OpenBSD: inet_pton.c,v 1.5 2005/03/25 13:24:12 otto Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_pton.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35
36/*
37 * WARNING: Don't even consider trying to compile this on a system where
38 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
39 */
40
41static int inet_pton4(const char *src, u_char *dst);
42static int inet_pton6(const char *src, u_char *dst);
43
44/* int
45 * inet_pton(af, src, dst)
46 * convert from presentation format (which usually means ASCII printable)
47 * to network format (which is usually some kind of binary format).
48 * return:
49 * 1 if the address was valid for the specified address family
50 * 0 if the address wasn't valid (`dst' is untouched in this case)
51 * -1 if some other error occurred (`dst' is untouched in this case, too)
52 * author:
53 * Paul Vixie, 1996.
54 */
55int
56inet_pton(int af, const char *src, void *dst)
57{
58 switch (af) {
59 case AF_INET:
60 return (inet_pton4(src, dst));
61 case AF_INET6:
62 return (inet_pton6(src, dst));
63 default:
64 errno = EAFNOSUPPORT;
65 return (-1);
66 }
67 /* NOTREACHED */
68}
69
70/* int
71 * inet_pton4(src, dst)
72 * like inet_aton() but without all the hexadecimal and shorthand.
73 * return:
74 * 1 if `src' is a valid dotted quad, else 0.
75 * notice:
76 * does not touch `dst' unless it's returning 1.
77 * author:
78 * Paul Vixie, 1996.
79 */
80static int
81inet_pton4(const char *src, u_char *dst)
82{
83 static const char digits[] = "0123456789";
84 int saw_digit, octets, ch;
85 u_char tmp[INADDRSZ], *tp;
86
87 saw_digit = 0;
88 octets = 0;
89 *(tp = tmp) = 0;
90 while ((ch = *src++) != '\0') {
91 const char *pch;
92
93 if ((pch = strchr(digits, ch)) != NULL) {
94 u_int new = *tp * 10 + (pch - digits);
95
96 if (new > 255)
97 return (0);
98 if (! saw_digit) {
99 if (++octets > 4)
100 return (0);
101 saw_digit = 1;
102 }
103 *tp = new;
104 } else if (ch == '.' && saw_digit) {
105 if (octets == 4)
106 return (0);
107 *++tp = 0;
108 saw_digit = 0;
109 } else
110 return (0);
111 }
112 if (octets < 4)
113 return (0);
114
115 memcpy(dst, tmp, INADDRSZ);
116 return (1);
117}
118
119/* int
120 * inet_pton6(src, dst)
121 * convert presentation level address to network order binary form.
122 * return:
123 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
124 * notice:
125 * (1) does not touch `dst' unless it's returning 1.
126 * (2) :: in a full address is silently ignored.
127 * credit:
128 * inspired by Mark Andrews.
129 * author:
130 * Paul Vixie, 1996.
131 */
132static int
133inet_pton6(const char *src, u_char *dst)
134{
135 static const char xdigits_l[] = "0123456789abcdef",
136 xdigits_u[] = "0123456789ABCDEF";
137 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
138 const char *xdigits, *curtok;
139 int ch, saw_xdigit;
140 u_int val;
141
142 memset((tp = tmp), '\0', IN6ADDRSZ);
143 endp = tp + IN6ADDRSZ;
144 colonp = NULL;
145 /* Leading :: requires some special handling. */
146 if (*src == ':')
147 if (*++src != ':')
148 return (0);
149 curtok = src;
150 saw_xdigit = 0;
151 val = 0;
152 while ((ch = *src++) != '\0') {
153 const char *pch;
154
155 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
156 pch = strchr((xdigits = xdigits_u), ch);
157 if (pch != NULL) {
158 val <<= 4;
159 val |= (pch - xdigits);
160 if (val > 0xffff)
161 return (0);
162 saw_xdigit = 1;
163 continue;
164 }
165 if (ch == ':') {
166 curtok = src;
167 if (!saw_xdigit) {
168 if (colonp)
169 return (0);
170 colonp = tp;
171 continue;
172 } else if (*src == '\0') {
173 return (0);
174 }
175 if (tp + INT16SZ > endp)
176 return (0);
177 *tp++ = (u_char) (val >> 8) & 0xff;
178 *tp++ = (u_char) val & 0xff;
179 saw_xdigit = 0;
180 val = 0;
181 continue;
182 }
183 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
184 inet_pton4(curtok, tp) > 0) {
185 tp += INADDRSZ;
186 saw_xdigit = 0;
187 break; /* '\0' was seen by inet_pton4(). */
188 }
189 return (0);
190 }
191 if (saw_xdigit) {
192 if (tp + INT16SZ > endp)
193 return (0);
194 *tp++ = (u_char) (val >> 8) & 0xff;
195 *tp++ = (u_char) val & 0xff;
196 }
197 if (colonp != NULL) {
198 /*
199 * Since some memmove()'s erroneously fail to handle
200 * overlapping regions, we'll do the shift by hand.
201 */
202 const int n = tp - colonp;
203 int i;
204
205 for (i = 1; i <= n; i++) {
206 endp[- i] = colonp[n - i];
207 colonp[n - i] = 0;
208 }
209 tp = endp;
210 }
211 if (tp != endp)
212 return (0);
213 memcpy(dst, tmp, IN6ADDRSZ);
214 return (1);
215}
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000000..565c0ed369
--- /dev/null
+++ b/src/lib/libc/net/ip6opt.c
@@ -0,0 +1,371 @@
1/* $OpenBSD: ip6opt.c,v 1.2 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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 <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
43static void inet6_insert_padopt(u_char *p, int len);
44
45/*
46 * This function returns the number of bytes required to hold an option
47 * when it is stored as ancillary data, including the cmsghdr structure
48 * at the beginning, and any padding at the end (to make its size a
49 * multiple of 8 bytes). The argument is the size of the structure
50 * defining the option, which must include any pad bytes at the
51 * beginning (the value y in the alignment term "xn + y"), the type
52 * byte, the length byte, and the option data.
53 */
54int
55inet6_option_space(int nbytes)
56{
57 nbytes += 2; /* we need space for nxt-hdr and length fields */
58 return(CMSG_SPACE((nbytes + 7) & ~7));
59}
60
61/*
62 * This function is called once per ancillary data object that will
63 * contain either Hop-by-Hop or Destination options. It returns 0 on
64 * success or -1 on an error.
65 */
66int
67inet6_option_init(void *bp, struct cmsghdr **cmsgp, int type)
68{
69 struct cmsghdr *ch = (struct cmsghdr *)bp;
70
71 /* argument validation */
72 if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
73 return(-1);
74
75 ch->cmsg_level = IPPROTO_IPV6;
76 ch->cmsg_type = type;
77 ch->cmsg_len = CMSG_LEN(0);
78
79 *cmsgp = ch;
80 return(0);
81}
82
83/*
84 * This function appends a Hop-by-Hop option or a Destination option
85 * into an ancillary data object that has been initialized by
86 * inet6_option_init(). This function returns 0 if it succeeds or -1 on
87 * an error.
88 * multx is the value x in the alignment term "xn + y" described
89 * earlier. It must have a value of 1, 2, 4, or 8.
90 * plusy is the value y in the alignment term "xn + y" described
91 * earlier. It must have a value between 0 and 7, inclusive.
92 */
93int
94inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx,
95 int plusy)
96{
97 int padlen, optlen, off;
98 u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
99 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
100
101 /* argument validation */
102 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
103 return(-1);
104 if (plusy < 0 || plusy > 7)
105 return(-1);
106 if (typep[0] > 255)
107 return(-1);
108
109 /*
110 * If this is the first option, allocate space for the
111 * first 2 bytes(for next header and length fields) of
112 * the option header.
113 */
114 if (bp == (u_char *)eh) {
115 bp += 2;
116 cmsg->cmsg_len += 2;
117 }
118
119 /* calculate pad length before the option. */
120 off = bp - (u_char *)eh;
121 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
122 (off % multx);
123 padlen += plusy;
124 padlen %= multx; /* keep the pad as short as possible */
125 /* insert padding */
126 inet6_insert_padopt(bp, padlen);
127 cmsg->cmsg_len += padlen;
128 bp += padlen;
129
130 /* copy the option */
131 if (typep[0] == IP6OPT_PAD1)
132 optlen = 1;
133 else
134 optlen = typep[1] + 2;
135 memcpy(bp, typep, optlen);
136 bp += optlen;
137 cmsg->cmsg_len += optlen;
138
139 /* calculate pad length after the option and insert the padding */
140 off = bp - (u_char *)eh;
141 padlen = ((off + 7) & ~7) - off;
142 inet6_insert_padopt(bp, padlen);
143 bp += padlen;
144 cmsg->cmsg_len += padlen;
145
146 /* update the length field of the ip6 option header */
147 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
148
149 return(0);
150}
151
152/*
153 * This function appends a Hop-by-Hop option or a Destination option
154 * into an ancillary data object that has been initialized by
155 * inet6_option_init(). This function returns a pointer to the 8-bit
156 * option type field that starts the option on success, or NULL on an
157 * error.
158 * The difference between this function and inet6_option_append() is
159 * that the latter copies the contents of a previously built option into
160 * the ancillary data object while the current function returns a
161 * pointer to the space in the data object where the option's TLV must
162 * then be built by the caller.
163 *
164 */
165u_int8_t *
166inet6_option_alloc(struct cmsghdr *cmsg, int datalen, int multx, int plusy)
167{
168 int padlen, off;
169 u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
170 u_int8_t *retval;
171 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
172
173 /* argument validation */
174 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
175 return(NULL);
176 if (plusy < 0 || plusy > 7)
177 return(NULL);
178
179 /*
180 * If this is the first option, allocate space for the
181 * first 2 bytes(for next header and length fields) of
182 * the option header.
183 */
184 if (bp == (u_char *)eh) {
185 bp += 2;
186 cmsg->cmsg_len += 2;
187 }
188
189 /* calculate pad length before the option. */
190 off = bp - (u_char *)eh;
191 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
192 (off % multx);
193 padlen += plusy;
194 padlen %= multx; /* keep the pad as short as possible */
195 /* insert padding */
196 inet6_insert_padopt(bp, padlen);
197 cmsg->cmsg_len += padlen;
198 bp += padlen;
199
200 /* keep space to store specified length of data */
201 retval = bp;
202 bp += datalen;
203 cmsg->cmsg_len += datalen;
204
205 /* calculate pad length after the option and insert the padding */
206 off = bp - (u_char *)eh;
207 padlen = ((off + 7) & ~7) - off;
208 inet6_insert_padopt(bp, padlen);
209 bp += padlen;
210 cmsg->cmsg_len += padlen;
211
212 /* update the length field of the ip6 option header */
213 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
214
215 return(retval);
216}
217
218/*
219 * This function processes the next Hop-by-Hop option or Destination
220 * option in an ancillary data object. If another option remains to be
221 * processed, the return value of the function is 0 and *tptrp points to
222 * the 8-bit option type field (which is followed by the 8-bit option
223 * data length, followed by the option data). If no more options remain
224 * to be processed, the return value is -1 and *tptrp is NULL. If an
225 * error occurs, the return value is -1 and *tptrp is not NULL.
226 * (RFC 2292, 6.3.5)
227 */
228int
229inet6_option_next(const struct cmsghdr *cmsg, u_int8_t **tptrp)
230{
231 struct ip6_ext *ip6e;
232 int hdrlen, optlen;
233 u_int8_t *lim;
234
235 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
236 (cmsg->cmsg_type != IPV6_HOPOPTS &&
237 cmsg->cmsg_type != IPV6_DSTOPTS))
238 return(-1);
239
240 /* message length validation */
241 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
242 return(-1);
243 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
244 hdrlen = (ip6e->ip6e_len + 1) << 3;
245 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
246 return(-1);
247
248 /*
249 * If the caller does not specify the starting point,
250 * simply return the 1st option.
251 * Otherwise, search the option list for the next option.
252 */
253 lim = (u_int8_t *)ip6e + hdrlen;
254 if (*tptrp == NULL)
255 *tptrp = (u_int8_t *)(ip6e + 1);
256 else {
257 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
258 return(-1);
259
260 *tptrp = *tptrp + optlen;
261 }
262 if (*tptrp >= lim) { /* there is no option */
263 *tptrp = NULL;
264 return(-1);
265 }
266 /*
267 * Finally, checks if the next option is safely stored in the
268 * cmsg data.
269 */
270 if (ip6optlen(*tptrp, lim) == 0)
271 return(-1);
272 else
273 return(0);
274}
275
276/*
277 * This function is similar to the inet6_option_next() function,
278 * except this function lets the caller specify the option type to be
279 * searched for, instead of always returning the next option in the
280 * ancillary data object.
281 * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
282 * it's a typo. The variable should be type of u_int8_t **.
283 */
284int
285inet6_option_find(const struct cmsghdr *cmsg, u_int8_t **tptrp, int type)
286{
287 struct ip6_ext *ip6e;
288 int hdrlen, optlen;
289 u_int8_t *optp, *lim;
290
291 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
292 (cmsg->cmsg_type != IPV6_HOPOPTS &&
293 cmsg->cmsg_type != IPV6_DSTOPTS))
294 return(-1);
295
296 /* message length validation */
297 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
298 return(-1);
299 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
300 hdrlen = (ip6e->ip6e_len + 1) << 3;
301 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
302 return(-1);
303
304 /*
305 * If the caller does not specify the starting point,
306 * search from the beginning of the option list.
307 * Otherwise, search from *the next option* of the specified point.
308 */
309 lim = (u_int8_t *)ip6e + hdrlen;
310 if (*tptrp == NULL)
311 *tptrp = (u_int8_t *)(ip6e + 1);
312 else {
313 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
314 return(-1);
315
316 *tptrp = *tptrp + optlen;
317 }
318 for (optp = *tptrp; optp < lim; optp += optlen) {
319 if (*optp == type) {
320 *tptrp = optp;
321 return(0);
322 }
323 if ((optlen = ip6optlen(optp, lim)) == 0)
324 return(-1);
325 }
326
327 /* search failed */
328 *tptrp = NULL;
329 return(-1);
330}
331
332/*
333 * Calculate the length of a given IPv6 option. Also checks
334 * if the option is safely stored in user's buffer according to the
335 * calculated length and the limitation of the buffer.
336 */
337static int
338ip6optlen(u_int8_t *opt, u_int8_t *lim)
339{
340 int optlen;
341
342 if (*opt == IP6OPT_PAD1)
343 optlen = 1;
344 else {
345 /* is there enough space to store type and len? */
346 if (opt + 2 > lim)
347 return(0);
348 optlen = *(opt + 1) + 2;
349 }
350 if (opt + optlen <= lim)
351 return(optlen);
352
353 return(0);
354}
355
356static void
357inet6_insert_padopt(u_char *p, int len)
358{
359 switch(len) {
360 case 0:
361 return;
362 case 1:
363 p[0] = IP6OPT_PAD1;
364 return;
365 default:
366 p[0] = IP6OPT_PADN;
367 p[1] = len - 2;
368 memset(&p[2], 0, len - 2);
369 return;
370 }
371}
diff --git a/src/lib/libc/net/ipx.3 b/src/lib/libc/net/ipx.3
new file mode 100644
index 0000000000..64f6028db0
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,123 @@
1.\" $OpenBSD: ipx.3,v 1.10 2003/06/02 20:18:35 millert Exp $
2.\"
3.\" Copyright (c) 1986, 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 June 4, 1993
31.Dt IPX 3
32.Os
33.Sh NAME
34.Nm ipx_addr ,
35.Nm ipx_ntoa
36.Nd IPX address conversion routines
37.Sh SYNOPSIS
38.Fd #include <sys/types.h>
39.Fd #include <netipx/ipx.h>
40.Ft struct ipx_addr
41.Fn ipx_addr "const char *cp"
42.Ft char *
43.Fn ipx_ntoa "struct ipx_addr ipx"
44.Sh DESCRIPTION
45The routine
46.Fn ipx_addr
47interprets character strings representing
48.Tn IPX
49addresses, returning binary information suitable
50for use in system calls.
51The routine
52.Fn ipx_ntoa
53takes
54.Tn IPX
55addresses and returns
56.Tn ASCII
57strings representing the address in a
58notation in common use:
59.Bd -filled -offset indent
60<network number>.<host number>.<port number>
61.Ed
62.Pp
63Trailing zero fields are suppressed, and each number is printed in hexadecimal,
64in a format suitable for input to
65.Fn ipx_addr .
66Any fields lacking super-decimal digits will have a
67trailing
68.Sq H
69appended.
70.Pp
71An effort has been made to ensure that
72.Fn ipx_addr
73be compatible with most formats in common use.
74It will first separate an address into 1 to 3 fields using a single delimiter
75chosen from
76period
77.Pq Ql \&. ,
78colon
79.Pq Ql \&: ,
80or pound-sign
81.Pq Ql # .
82Each field is then examined for byte separators (colon or period).
83If there are byte separators, each subfield separated is taken to be
84a small hexadecimal number, and the entirety is taken as a network-byte-ordered
85quantity to be zero extended in the high-network-order bytes.
86Next, the field is inspected for hyphens, in which case
87the field is assumed to be a number in decimal notation
88with hyphens separating the millenia.
89Next, the field is assumed to be a number:
90It is interpreted
91as hexadecimal if there is a leading
92.Ql 0x
93(as in C),
94a trailing
95.Sq H
96(as in Mesa), or there are any super-decimal digits present.
97It is interpreted as octal if there is a leading
98.Ql 0
99and there are no super-octal digits.
100Otherwise, it is converted as a decimal number.
101.Sh RETURN VALUES
102None.
103(See
104.Sx BUGS . )
105.Sh SEE ALSO
106.Xr ns 4 ,
107.Xr hosts 5 ,
108.Xr networks 5
109.Sh HISTORY
110The precursor
111.Fn ns_addr
112and
113.Fn ns_ntoa
114functions appeared in
115.Bx 4.3 .
116.Sh BUGS
117The string returned by
118.Fn ipx_ntoa
119resides in a static memory area.
120The function
121.Fn ipx_addr
122should diagnose improperly formed input, and there should be an unambiguous
123way to recognize this.
diff --git a/src/lib/libc/net/ipx_addr.c b/src/lib/libc/net/ipx_addr.c
new file mode 100644
index 0000000000..c7f8306128
--- /dev/null
+++ b/src/lib/libc/net/ipx_addr.c
@@ -0,0 +1,216 @@
1/*
2 * Copyright (c) 1986, 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 * J.Q. Johnson.
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 * from @(#)ipx_addr.c
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char rcsid[] = "$OpenBSD: ipx_addr.c,v 1.7 2005/03/25 13:24:12 otto Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/param.h>
40#include <netipx/ipx.h>
41#include <stdio.h>
42#include <string.h>
43
44static struct ipx_addr addr, zero_addr;
45
46static void Field(char *, u_char *, int);
47static void cvtbase(long, int, int *, int, unsigned char *, int);
48
49struct ipx_addr
50ipx_addr(const char *name)
51{
52 char separator;
53 char *hostname, *socketname, *cp;
54 char buf[50];
55
56 strlcpy(buf, name, sizeof(buf));
57
58 /*
59 * First, figure out what he intends as a field separtor.
60 * Despite the way this routine is written, the prefered
61 * form 2-272.AA001234H.01777, i.e. XDE standard.
62 * Great efforts are made to insure backward compatibility.
63 */
64 if ((hostname = strchr(buf, '#')))
65 separator = '#';
66 else {
67 hostname = strchr(buf, '.');
68 if ((cp = strchr(buf, ':')) &&
69 ((hostname && cp < hostname) || (hostname == 0))) {
70 hostname = cp;
71 separator = ':';
72 } else
73 separator = '.';
74 }
75 if (hostname)
76 *hostname++ = 0;
77
78 addr = zero_addr;
79 Field(buf, addr.ipx_net.c_net, 4);
80 if (hostname == 0)
81 return (addr); /* No separator means net only */
82
83 socketname = strchr(hostname, separator);
84 if (socketname) {
85 *socketname++ = 0;
86 Field(socketname, (u_char *)&addr.ipx_port, 2);
87 }
88
89 Field(hostname, addr.ipx_host.c_host, 6);
90
91 return (addr);
92}
93
94static void
95Field(char *buf, u_char *out, int len)
96{
97 char *bp = buf;
98 int i, ibase, base16 = 0, base10 = 0, clen = 0;
99 int hb[6], *hp;
100 char *fmt;
101
102 /*
103 * first try 2-273#2-852-151-014#socket
104 */
105 if ((*buf != '-') &&
106 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
107 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
108 cvtbase(1000L, 256, hb, i, out, len);
109 return;
110 }
111 /*
112 * try form 8E1#0.0.AA.0.5E.E6#socket
113 */
114 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
115 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
116 cvtbase(256L, 256, hb, i, out, len);
117 return;
118 }
119 /*
120 * try form 8E1#0:0:AA:0:5E:E6#socket
121 */
122 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
123 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
124 cvtbase(256L, 256, hb, i, out, len);
125 return;
126 }
127 /*
128 * This is REALLY stretching it but there was a
129 * comma notation separting shorts -- definitely non standard
130 */
131 if (1 < (i = sscanf(buf,"%x,%x,%x",
132 &hb[0], &hb[1], &hb[2]))) {
133 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
134 hb[2] = htons(hb[2]);
135 cvtbase(65536L, 256, hb, i, out, len);
136 return;
137 }
138
139 /* Need to decide if base 10, 16 or 8 */
140 while (*bp) switch (*bp++) {
141
142 case '0': case '1': case '2': case '3': case '4': case '5':
143 case '6': case '7': case '-':
144 break;
145
146 case '8': case '9':
147 base10 = 1;
148 break;
149
150 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
151 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
152 base16 = 1;
153 break;
154
155 case 'x': case 'X':
156 *--bp = '0';
157 base16 = 1;
158 break;
159
160 case 'h': case 'H':
161 base16 = 1;
162 /* fall into */
163
164 default:
165 *--bp = 0; /* Ends Loop */
166 }
167 if (base16) {
168 fmt = "%3x";
169 ibase = 4096;
170 } else if (base10 == 0 && *buf == '0') {
171 fmt = "%3o";
172 ibase = 512;
173 } else {
174 fmt = "%3d";
175 ibase = 1000;
176 }
177
178 for (bp = buf; *bp++; ) clen++;
179 if (clen == 0) clen++;
180 if (clen > 18) clen = 18;
181 i = ((clen - 1) / 3) + 1;
182 bp = clen + buf - 3;
183 hp = hb + i - 1;
184
185 while (hp > hb) {
186 (void)sscanf(bp, fmt, hp);
187 bp[0] = 0;
188 hp--;
189 bp -= 3;
190 }
191 (void)sscanf(buf, fmt, hp);
192 cvtbase((long)ibase, 256, hb, i, out, len);
193}
194
195static void
196cvtbase(long oldbase, int newbase, int *input, int inlen,
197 unsigned char *result, int reslen)
198{
199 int d, e;
200 long sum;
201
202 e = 1;
203 while (e > 0 && reslen > 0) {
204 d = 0; e = 0; sum = 0;
205 /* long division: input=input/newbase */
206 while (d < inlen) {
207 sum = sum*oldbase + (long) input[d];
208 e += (sum > 0);
209 input[d++] = sum / newbase;
210 sum %= newbase;
211 }
212 result[--reslen] = sum; /* accumulate remainder */
213 }
214 for (d=0; d < reslen; d++)
215 result[d] = 0;
216}
diff --git a/src/lib/libc/net/ipx_ntoa.c b/src/lib/libc/net/ipx_ntoa.c
new file mode 100644
index 0000000000..64ba146b31
--- /dev/null
+++ b/src/lib/libc/net/ipx_ntoa.c
@@ -0,0 +1,49 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ipx_ntoa.c,v 1.5 2003/09/26 06:19:25 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netipx/ipx.h>
36#include <stdio.h>
37
38char *
39ipx_ntoa(struct ipx_addr addr)
40{
41 static char obuf[] = "xxxxxxxxH.xx:xx:xx:xx:xx:xx.uuuuu";
42
43 snprintf(obuf, sizeof obuf, "%8xH.%02x:%02x:%02x:%02x:%02x:%02x.%u",
44 ntohl(addr.ipx_net.l_net), addr.ipx_host.c_host[0],
45 addr.ipx_host.c_host[1], addr.ipx_host.c_host[2],
46 addr.ipx_host.c_host[3], addr.ipx_host.c_host[4],
47 addr.ipx_host.c_host[5], ntohs(addr.ipx_port));
48 return (obuf);
49}
diff --git a/src/lib/libc/net/link_addr.3 b/src/lib/libc/net/link_addr.3
new file mode 100644
index 0000000000..0f8787e191
--- /dev/null
+++ b/src/lib/libc/net/link_addr.3
@@ -0,0 +1,126 @@
1.\" $OpenBSD: link_addr.3,v 1.10 2005/02/25 03:12:43 cloder Exp $
2.\"
3.\" Copyright (c) 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.\" Donn Seeley at BSDI.
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.Dd July 28, 1993
34.Dt LINK_ADDR 3
35.Os
36.Sh NAME
37.Nm link_addr ,
38.Nm link_ntoa
39.Nd elementary address specification routines for link level access
40.Sh SYNOPSIS
41.Fd #include <sys/types.h>
42.Fd #include <sys/socket.h>
43.Fd #include <net/if_dl.h>
44.Ft void
45.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
46.Ft char *
47.Fn link_ntoa "const struct sockaddr_dl *sdl"
48.Sh DESCRIPTION
49The
50.Fn link_addr
51function interprets character strings representing
52link-level addresses, returning binary information suitable
53for use in system calls.
54.Fn link_ntoa
55takes
56a link-level
57address and returns an
58.Tn ASCII
59string representing some of the information present,
60including the link level address itself, and the interface name
61or number, if present.
62This facility is experimental and is
63still subject to change.
64.Pp
65For
66.Fn link_addr ,
67the string
68.Fa addr
69may contain
70an optional network interface identifier of the form
71.Dq name unit-number ,
72suitable for the first argument to
73.Xr ifconfig 8 ,
74followed in all cases by a colon and
75an interface address in the form of
76groups of hexadecimal digits
77separated by periods.
78Each group represents a byte of address;
79address bytes are filled left to right from
80low order bytes through high order bytes.
81.Pp
82.\" A regular expression may make this format clearer:
83.\" .Bd -literal -offset indent
84.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
85.\" .Ed
86.\" .Pp
87Thus
88.Li le0:8.0.9.13.d.30
89represents an Ethernet address
90to be transmitted on the first Lance Ethernet interface.
91.Sh RETURN VALUES
92.Fn link_ntoa
93always returns a NUL-terminated string.
94.Fn link_addr
95has no return value.
96(See
97.Sx BUGS . )
98.Sh SEE ALSO
99.Xr ifconfig 8
100.Sh HISTORY
101The
102.Fn link_addr
103and
104.Fn link_ntoa
105functions appeared in
106.Bx 4.3 Reno .
107.Sh BUGS
108The returned values for link_ntoa
109reside in a static memory area.
110.Pp
111The function
112.Fn link_addr
113should diagnose improperly formed input, and there should be an unambiguous
114way to recognize this.
115.Pp
116If the
117.Fa sdl_len
118field of the link socket address
119.Fa sdl
120is 0,
121.Fn link_ntoa
122will not insert a colon before the interface address bytes.
123If this translated address is given to
124.Fn link_addr
125without inserting an initial colon,
126the latter will not interpret it correctly.
diff --git a/src/lib/libc/net/linkaddr.c b/src/lib/libc/net/linkaddr.c
new file mode 100644
index 0000000000..fcb0164ca4
--- /dev/null
+++ b/src/lib/libc/net/linkaddr.c
@@ -0,0 +1,151 @@
1/*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: linkaddr.c,v 1.4 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <net/if_dl.h>
37#include <string.h>
38
39/* States*/
40#define NAMING 0
41#define GOTONE 1
42#define GOTTWO 2
43#define RESET 3
44/* Inputs */
45#define DIGIT (4*0)
46#define END (4*1)
47#define DELIM (4*2)
48#define LETTER (4*3)
49
50void
51link_addr(const char *addr, struct sockaddr_dl *sdl)
52{
53 char *cp = sdl->sdl_data;
54 char *cplim = sdl->sdl_len + (char *)sdl;
55 int byte = 0, state = NAMING, new;
56
57 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
58 sdl->sdl_family = AF_LINK;
59 do {
60 state &= ~LETTER;
61 if ((*addr >= '0') && (*addr <= '9')) {
62 new = *addr - '0';
63 } else if ((*addr >= 'a') && (*addr <= 'f')) {
64 new = *addr - 'a' + 10;
65 } else if ((*addr >= 'A') && (*addr <= 'F')) {
66 new = *addr - 'A' + 10;
67 } else if (*addr == 0) {
68 state |= END;
69 } else if (state == NAMING &&
70 (((*addr >= 'A') && (*addr <= 'Z')) ||
71 ((*addr >= 'a') && (*addr <= 'z'))))
72 state |= LETTER;
73 else
74 state |= DELIM;
75 addr++;
76 switch (state /* | INPUT */) {
77 case NAMING | DIGIT:
78 case NAMING | LETTER:
79 *cp++ = addr[-1];
80 continue;
81 case NAMING | DELIM:
82 state = RESET;
83 sdl->sdl_nlen = cp - sdl->sdl_data;
84 continue;
85 case GOTTWO | DIGIT:
86 *cp++ = byte;
87 /* FALLTHROUGH */
88 case RESET | DIGIT:
89 state = GOTONE;
90 byte = new;
91 continue;
92 case GOTONE | DIGIT:
93 state = GOTTWO;
94 byte = new + (byte << 4);
95 continue;
96 default: /* | DELIM */
97 state = RESET;
98 *cp++ = byte;
99 byte = 0;
100 continue;
101 case GOTONE | END:
102 case GOTTWO | END:
103 *cp++ = byte;
104 /* FALLTHROUGH */
105 case RESET | END:
106 break;
107 }
108 break;
109 } while (cp < cplim);
110 sdl->sdl_alen = cp - LLADDR(sdl);
111 new = cp - (char *)sdl;
112 if (new > sizeof(*sdl))
113 sdl->sdl_len = new;
114 return;
115}
116
117static char hexlist[] = "0123456789abcdef";
118
119char *
120link_ntoa(const struct sockaddr_dl *sdl)
121{
122 static char obuf[64];
123 char *out = obuf;
124 int i;
125 u_char *in = (u_char *)LLADDR(sdl);
126 u_char *inlim = in + sdl->sdl_alen;
127 int firsttime = 1;
128
129 if (sdl->sdl_nlen) {
130 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
131 out += sdl->sdl_nlen;
132 if (sdl->sdl_alen)
133 *out++ = ':';
134 }
135 while (in < inlim) {
136 if (firsttime)
137 firsttime = 0;
138 else
139 *out++ = '.';
140 i = *in++;
141 if (i > 0xf) {
142 out[1] = hexlist[i & 0xf];
143 i >>= 4;
144 out[0] = hexlist[i];
145 out += 2;
146 } else
147 *out++ = hexlist[i];
148 }
149 *out = 0;
150 return (obuf);
151}
diff --git a/src/lib/libc/net/net_addrcmp.3 b/src/lib/libc/net/net_addrcmp.3
new file mode 100644
index 0000000000..f1ce4c8cd1
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.3
@@ -0,0 +1,91 @@
1.\" $OpenBSD: net_addrcmp.3,v 1.3 2001/08/07 06:53:27 deraadt Exp $
2.\"
3.\" Copyright (c) 1999 Theo de Raadt
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.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\"
25.Dd July 3, 1999
26.Dt NET_ADDRCMP 3
27.Os
28.Sh NAME
29.Nm net_addrcmp
30.Nd compare socket address structures
31.Sh SYNOPSIS
32.Fd #include <netdb.h>
33.Ft int
34.Fn net_addrcmp "struct sockaddr *sa1" "struct sockaddr *sa2"
35.Sh DESCRIPTION
36The
37.Fn net_addrcmp
38function compares two socket address structures,
39.Fa sa1
40and
41.Fa sa2 .
42.Sh RETURN VALUES
43If
44.Fa sa1
45and
46.Fa sa2
47are for the same address,
48.Fn net_addrcmp
49returns 0.
50.Pp
51The
52.Fa sa_len
53fields are compared first.
54If they do not match,
55.Fn net_addrcmp
56returns \-1 or 1 if
57.Li sa1->sa_len
58is less than or greater than
59.Li sa2->sa_len ,
60respectively.
61.Pp
62Next, the
63.Fa sa_family
64members are compared.
65If they do not match,
66.Fn net_addrcmp
67returns \-1 or 1 if
68.Li sa1->sa_family
69is less than or greater than
70.Li sa2->sa_family ,
71respectively.
72.Pp
73Lastly, if each socket address structure's
74.Fa sa_len
75and
76.Fa sa_family
77fields match,
78the protocol-specific data (the
79.Fa sa_data
80field) is compared.
81If there's a match, both
82.Fa sa1
83and
84.Fa sa2
85must refer to the same address, and 0 is returned; otherwise, a value >0
86or <0 is returned.
87.Sh HISTORY
88A
89.Fn net_addrcmp
90function was added in
91.Ox 2.5 .
diff --git a/src/lib/libc/net/net_addrcmp.c b/src/lib/libc/net/net_addrcmp.c
new file mode 100644
index 0000000000..8f8f694f4c
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.c
@@ -0,0 +1,68 @@
1/* $OpenBSD: net_addrcmp.c,v 1.9 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 1999 Theo de Raadt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/un.h>
31#include <netinet/in.h>
32#include <netns/ns.h>
33#include <string.h>
34
35int
36net_addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
37{
38
39 if (sa1->sa_len != sa2->sa_len)
40 return (sa1->sa_len < sa2->sa_len) ? -1 : 1;
41 if (sa1->sa_family != sa2->sa_family)
42 return (sa1->sa_family < sa2->sa_family) ? -1 : 1;
43
44 switch(sa1->sa_family) {
45 case AF_INET:
46 return (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,
47 &((struct sockaddr_in *)sa2)->sin_addr,
48 sizeof(struct in_addr)));
49 case AF_INET6:
50 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
51 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
52 return (((struct sockaddr_in6 *)sa1)->sin6_scope_id <
53 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
54 ? -1 : 1;
55 return memcmp(&((struct sockaddr_in6 *)sa1)->sin6_addr,
56 &((struct sockaddr_in6 *)sa2)->sin6_addr,
57 sizeof(struct in6_addr));
58 case AF_NS:
59 return (memcmp(&((struct sockaddr_ns *)sa1)->sns_addr,
60 &((struct sockaddr_ns *)sa2)->sns_addr,
61 sizeof(struct ns_addr)));
62 case AF_LOCAL:
63 return (strcmp(((struct sockaddr_un *)sa1)->sun_path,
64 ((struct sockaddr_un *)sa1)->sun_path));
65 default:
66 return -1;
67 }
68}
diff --git a/src/lib/libc/net/ns.3 b/src/lib/libc/net/ns.3
new file mode 100644
index 0000000000..9c7aeab312
--- /dev/null
+++ b/src/lib/libc/net/ns.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: ns.3,v 1.9 2003/06/02 20:18:35 millert Exp $
2.\"
3.\" Copyright (c) 1986, 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 June 4, 1993
31.Dt NS 3
32.Os
33.Sh NAME
34.Nm ns_addr ,
35.Nm ns_ntoa
36.Nd Xerox
37.Tn NS Ns (tm)
38address conversion routines
39.Sh SYNOPSIS
40.Fd #include <sys/types.h>
41.Fd #include <netns/ns.h>
42.Ft struct ns_addr
43.Fn ns_addr "char *cp"
44.Ft char *
45.Fn ns_ntoa "struct ns_addr ns"
46.Sh DESCRIPTION
47The routine
48.Fn ns_addr
49interprets character strings representing
50.Tn XNS
51addresses, returning binary information suitable
52for use in system calls.
53The routine
54.Fn ns_ntoa
55takes
56.Tn XNS
57addresses and returns
58.Tn ASCII
59strings representing the address in a
60notation in common use in the Xerox Development Environment:
61.Bd -filled -offset indent
62<network number>.<host number>.<port number>
63.Ed
64.Pp
65Trailing zero fields are suppressed, and each number is printed in hexadecimal,
66in a format suitable for input to
67.Fn ns_addr .
68Any fields lacking super-decimal digits will have a
69trailing
70.Sq H
71appended.
72.Pp
73Unfortunately, no universal standard exists for representing
74.Tn XNS
75addresses.
76An effort has been made to ensure that
77.Fn ns_addr
78be compatible with most formats in common use.
79It will first separate an address into 1 to 3 fields using a single delimiter
80chosen from
81period
82.Pq Ql \&. ,
83colon
84.Pq Ql \&: ,
85or pound-sign
86.Ql # .
87Each field is then examined for byte separators (colon or period).
88If there are byte separators, each subfield separated is taken to be
89a small hexadecimal number, and the entirety is taken as a network-byte-ordered
90quantity to be zero extended in the high-network-order bytes.
91Next, the field is inspected for hyphens, in which case
92the field is assumed to be a number in decimal notation
93with hyphens separating the millenia.
94Next, the field is assumed to be a number:
95It is interpreted
96as hexadecimal if there is a leading
97.Ql 0x
98(as in C),
99a trailing
100.Sq H
101(as in Mesa), or there are any super-decimal digits present.
102It is interpreted as octal if there is a leading
103.Ql 0
104and there are no super-octal digits.
105Otherwise, it is converted as a decimal number.
106.Sh RETURN VALUES
107None.
108(See
109.Sx BUGS . )
110.Sh SEE ALSO
111.Xr hosts 5 ,
112.Xr networks 5
113.Sh HISTORY
114The
115.Fn ns_addr
116and
117.Fn ns_toa
118functions appeared in
119.Bx 4.3 .
120.Sh BUGS
121The string returned by
122.Fn ns_ntoa
123resides in a static memory area.
124The function
125.Fn ns_addr
126should diagnose improperly formed input, and there should be an unambiguous
127way to recognize this.
diff --git a/src/lib/libc/net/ns_addr.c b/src/lib/libc/net/ns_addr.c
new file mode 100644
index 0000000000..03b14909c5
--- /dev/null
+++ b/src/lib/libc/net/ns_addr.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (c) 1986, 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 * J.Q. Johnson.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char rcsid[] = "$OpenBSD: ns_addr.c,v 1.9 2005/03/25 13:24:12 otto Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/param.h>
38#include <netns/ns.h>
39#include <stdio.h>
40#include <string.h>
41
42static struct ns_addr addr, zero_addr;
43
44static void Field(char *, u_int8_t *, int);
45static void cvtbase(long, int, int[], int, u_int8_t[], int);
46
47struct ns_addr
48ns_addr(const char *name)
49{
50 char separator;
51 char *hostname, *socketname, *cp;
52 char buf[50];
53
54 strlcpy(buf, name, sizeof(buf));
55
56 /*
57 * First, figure out what he intends as a field separtor.
58 * Despite the way this routine is written, the prefered
59 * form 2-272.AA001234H.01777, i.e. XDE standard.
60 * Great efforts are made to insure backward compatibility.
61 */
62 if ((hostname = strchr(buf, '#')))
63 separator = '#';
64 else {
65 hostname = strchr(buf, '.');
66 if ((cp = strchr(buf, ':')) &&
67 ((hostname && cp < hostname) || (hostname == 0))) {
68 hostname = cp;
69 separator = ':';
70 } else
71 separator = '.';
72 }
73 if (hostname)
74 *hostname++ = 0;
75
76 addr = zero_addr;
77 Field(buf, addr.x_net.c_net, 4);
78 if (hostname == 0)
79 return (addr); /* No separator means net only */
80
81 socketname = strchr(hostname, separator);
82 if (socketname) {
83 *socketname++ = 0;
84 Field(socketname, (u_char *)&addr.x_port, 2);
85 }
86
87 Field(hostname, (u_char *)addr.x_host.c_host, 6);
88
89 return (addr);
90}
91
92static void
93Field(char *buf, u_char *out, int len)
94{
95 char *bp = buf;
96 int i, ibase, base16 = 0, base10 = 0, clen = 0;
97 int hb[6], *hp;
98 char *fmt;
99
100 /*
101 * first try 2-273#2-852-151-014#socket
102 */
103 if ((*buf != '-') &&
104 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
105 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
106 cvtbase(1000L, 256, hb, i, out, len);
107 return;
108 }
109 /*
110 * try form 8E1#0.0.AA.0.5E.E6#socket
111 */
112 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
113 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
114 cvtbase(256L, 256, hb, i, out, len);
115 return;
116 }
117 /*
118 * try form 8E1#0:0:AA:0:5E:E6#socket
119 */
120 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
121 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
122 cvtbase(256L, 256, hb, i, out, len);
123 return;
124 }
125 /*
126 * This is REALLY stretching it but there was a
127 * comma notation separting shorts -- definitely non standard
128 */
129 if (1 < (i = sscanf(buf,"%x,%x,%x",
130 &hb[0], &hb[1], &hb[2]))) {
131 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
132 hb[2] = htons(hb[2]);
133 cvtbase(65536L, 256, hb, i, out, len);
134 return;
135 }
136
137 /* Need to decide if base 10, 16 or 8 */
138 while (*bp) switch (*bp++) {
139
140 case '0': case '1': case '2': case '3': case '4': case '5':
141 case '6': case '7': case '-':
142 break;
143
144 case '8': case '9':
145 base10 = 1;
146 break;
147
148 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
149 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
150 base16 = 1;
151 break;
152
153 case 'x': case 'X':
154 *--bp = '0';
155 base16 = 1;
156 break;
157
158 case 'h': case 'H':
159 base16 = 1;
160 /* fall into */
161
162 default:
163 *--bp = 0; /* Ends Loop */
164 }
165 if (base16) {
166 fmt = "%3x";
167 ibase = 4096;
168 } else if (base10 == 0 && *buf == '0') {
169 fmt = "%3o";
170 ibase = 512;
171 } else {
172 fmt = "%3d";
173 ibase = 1000;
174 }
175
176 for (bp = buf; *bp++; ) clen++;
177 if (clen == 0) clen++;
178 if (clen > 18) clen = 18;
179 i = ((clen - 1) / 3) + 1;
180 bp = clen + buf - 3;
181 hp = hb + i - 1;
182
183 while (hp > hb) {
184 (void)sscanf(bp, fmt, hp);
185 bp[0] = 0;
186 hp--;
187 bp -= 3;
188 }
189 (void)sscanf(buf, fmt, hp);
190 cvtbase((long)ibase, 256, hb, i, out, len);
191}
192
193static void
194cvtbase(long int oldbase, int newbase, int *input, int inlen,
195 unsigned char *result, int reslen)
196{
197 int d, e;
198 long sum;
199
200 e = 1;
201 while (e > 0 && reslen > 0) {
202 d = 0; e = 0; sum = 0;
203 /* long division: input=input/newbase */
204 while (d < inlen) {
205 sum = sum*oldbase + (long) input[d];
206 e += (sum > 0);
207 input[d++] = sum / newbase;
208 sum %= newbase;
209 }
210 result[--reslen] = sum; /* accumulate remainder */
211 }
212 for (d=0; d < reslen; d++)
213 result[d] = 0;
214}
diff --git a/src/lib/libc/net/ns_ntoa.c b/src/lib/libc/net/ns_ntoa.c
new file mode 100644
index 0000000000..fd67e459da
--- /dev/null
+++ b/src/lib/libc/net/ns_ntoa.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ns_ntoa.c,v 1.13 2003/09/25 21:14:46 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netns/ns.h>
36#include <stdio.h>
37
38static char *spectHex(char *);
39
40char *
41ns_ntoa(struct ns_addr addr)
42{
43 static char obuf[40];
44 union { union ns_net net_e; u_int32_t long_e; } net;
45 in_port_t port = htons(addr.x_port);
46 char *cp, *cp2;
47 u_char *up = addr.x_host.c_host;
48 u_char *uplim = up + 6;
49 size_t rem;
50
51 net.net_e = addr.x_net;
52 snprintf(obuf, sizeof obuf, "%x", ntohl(net.long_e));
53 cp = spectHex(obuf);
54 rem = sizeof(obuf) - (cp - obuf);
55 cp2 = cp + 1;
56 while (up < uplim && *up==0)
57 up++;
58 if (up == uplim) {
59 if (port) {
60 snprintf(cp, rem, ".0");
61 cp += 2;
62 rem -= 2;
63 }
64 } else {
65 snprintf(cp, rem, ".%x", *up++);
66 while (up < uplim) {
67 while (*cp) {
68 cp++;
69 rem--;
70 }
71 snprintf(cp, rem, "%02x", *up++);
72 }
73 cp = spectHex(cp2);
74 rem = sizeof(obuf) - (cp - obuf);
75 }
76 if (port) {
77 snprintf(cp, rem, ".%x", port);
78 spectHex(cp + 1);
79 }
80 return (obuf);
81}
82
83static char *
84spectHex(char *p0)
85{
86 int ok = 0, nonzero = 0;
87 char *p = p0;
88
89 for (; *p; p++) {
90 switch (*p) {
91 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
92 *p += ('A' - 'a');
93 /* fall into . . . */
94 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
95 ok = 1;
96 case '1': case '2': case '3': case '4': case '5':
97 case '6': case '7': case '8': case '9':
98 nonzero = 1;
99 }
100 }
101 if (nonzero && !ok) {
102 *p++ = 'H';
103 *p = 0;
104 }
105 return (p);
106}
diff --git a/src/lib/libc/net/nsap_addr.c b/src/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000000..58c0d5e493
--- /dev/null
+++ b/src/lib/libc/net/nsap_addr.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: nsap_addr.c,v 1.5 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static char rcsid[] = "$From: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
23#else
24static char rcsid[] = "$OpenBSD: nsap_addr.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
25#endif
26#endif /* LIBC_SCCS and not lint */
27
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/nameser.h>
33#include <ctype.h>
34#include <resolv.h>
35
36static char
37xtob(int c)
38{
39 return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
40}
41
42u_int
43inet_nsap_addr(const char *ascii, u_char *binary, int maxlen)
44{
45 u_char c, nib;
46 u_int len = 0;
47
48 while ((c = *ascii++) != '\0' && len < maxlen) {
49 if (c == '.' || c == '+' || c == '/')
50 continue;
51 if (!isascii(c))
52 return (0);
53 if (islower(c))
54 c = toupper(c);
55 if (isxdigit(c)) {
56 nib = xtob(c);
57 if ((c = *ascii++)) {
58 c = toupper(c);
59 if (isxdigit(c)) {
60 *binary++ = (nib << 4) | xtob(c);
61 len++;
62 } else
63 return (0);
64 }
65 else
66 return (0);
67 }
68 else
69 return (0);
70 }
71 return (len);
72}
73
74char *
75inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii)
76{
77 int nib;
78 int i;
79 static char tmpbuf[255*3];
80 char *start;
81
82 if (ascii)
83 start = ascii;
84 else {
85 ascii = tmpbuf;
86 start = tmpbuf;
87 }
88
89 if (binlen > 255)
90 binlen = 255;
91
92 for (i = 0; i < binlen; i++) {
93 nib = *binary >> 4;
94 *ascii++ = nib + (nib < 10 ? '0' : '7');
95 nib = *binary++ & 0x0f;
96 *ascii++ = nib + (nib < 10 ? '0' : '7');
97 if (((i % 2) == 0 && (i + 1) < binlen))
98 *ascii++ = '.';
99 }
100 *ascii = '\0';
101 return (start);
102}
diff --git a/src/lib/libc/net/ntohl.c b/src/lib/libc/net/ntohl.c
new file mode 100644
index 0000000000..c8b2ca2bb5
--- /dev/null
+++ b/src/lib/libc/net/ntohl.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: ntohl.c,v 1.5 2005/03/25 13:24:12 otto Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef ntohl
14
15u_int32_t
16ntohl(u_int32_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *)&x;
20 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/ntohs.c b/src/lib/libc/net/ntohs.c
new file mode 100644
index 0000000000..4c3ab33f31
--- /dev/null
+++ b/src/lib/libc/net/ntohs.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: ntohs.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef ntohs
14
15u_int16_t
16ntohs(u_int16_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *) &x;
20 return (u_int16_t)(s[0] << 8 | s[1]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/rcmd.3 b/src/lib/libc/net/rcmd.3
new file mode 100644
index 0000000000..df31a60b63
--- /dev/null
+++ b/src/lib/libc/net/rcmd.3
@@ -0,0 +1,266 @@
1.\" $OpenBSD: rcmd.3,v 1.26 2003/06/02 20:18:35 millert Exp $
2.\"
3.\" Copyright (c) 1983, 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 June 4, 1993
31.Dt RCMD 3
32.Os
33.Sh NAME
34.Nm rcmd ,
35.Nm rcmd_af ,
36.Nm rresvport ,
37.Nm rresvport_af ,
38.Nm iruserok ,
39.Nm ruserok ,
40.Nm iruserok_sa
41.Nd routines for returning a stream to a remote command
42.Sh SYNOPSIS
43.Fd #include <unistd.h>
44.Ft int
45.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
46.Ft int
47.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
48.Ft int
49.Fn rresvport "int *port"
50.Ft int
51.Fn rresvport_af "int *port" "int af"
52.Ft int
53.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser"
54.Ft int
55.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
56.Ft int
57.Fn iruserok_sa "const void *sa" "int salen" "int superuser" "const char *ruser" "const char *luser"
58.Sh DESCRIPTION
59The
60.Fn rcmd
61function is used by the superuser to execute a command on a remote
62machine using an authentication scheme based on reserved
63port numbers.
64If the calling process is not setuid, the
65.Ev RSH
66environment variable is set, and
67.Fa inport
68is
69.Dq shell/tcp ,
70.Xr rcmdsh 3
71is called instead with the value of
72.Ev RSH .
73Alternately, if the user is not the superuser,
74.Fn rcmd
75will invoke
76.Xr rcmdsh 3
77to run the command via
78.Xr rsh 1 .
79While
80.Fn rcmd
81can handle IPv4 cases only,
82the
83.Fn rcmd_af
84function can handle other cases as well.
85.Pp
86The
87.Fn rresvport
88and
89.Fn rresvport_af
90functions return a descriptor to a socket
91with an address in the privileged port space.
92The
93.Fn iruserok
94and
95.Fn ruserok
96functions are used by servers
97to authenticate clients requesting service with
98.Fn rcmd .
99All four functions are present in the same file and are used
100by the
101.Xr rshd 8
102server (among others).
103.Fn iruserok_sa
104is an address family independent variant of
105.Fn iruserok .
106.Pp
107The
108.Fn rcmd
109function looks up the host
110.Fa *ahost
111using
112.Xr gethostbyname 3 ,
113returning \-1 if the host does not exist.
114Otherwise
115.Fa *ahost
116is set to the standard name of the host
117and a connection is established to a server
118residing at the well-known Internet port
119.Fa inport .
120If the user is not the superuser, the only valid port is
121.Dq shell/tcp
122(usually port 514).
123.Pp
124If the connection succeeds,
125a socket in the Internet domain of type
126.Dv SOCK_STREAM
127is returned to the caller, and given to the remote
128command as stdin and stdout.
129If
130.Fa fd2p
131is non-zero, then an auxiliary channel to a control
132process will be set up, and a descriptor for it will be placed
133in
134.Fa *fd2p .
135The control process will return diagnostic
136output from the command (unit 2) on this channel, and will also
137accept bytes on this channel as being
138.Tn UNIX
139signal numbers, to be
140forwarded to the process group of the command.
141If
142.Fa fd2p
143is
144.Va NULL ,
145then the standard error (unit 2 of the remote command) will be made
146the same as the standard output and no provision is made for sending
147arbitrary signals to the remote process, although you may be able to
148get its attention by using out-of-band data.
149Note that if the user is not the superuser,
150.Fa fd2p
151must be
152.Va NULL .
153.Pp
154.Fn rcmd_af
155takes address family in the last argument.
156If the last argument is
157.Dv PF_UNSPEC ,
158interpretation of
159.Fa *ahost
160will obey the underlying address resolution like DNS.
161.Pp
162The protocol is described in detail in
163.Xr rshd 8 .
164.Pp
165The
166.Fn rresvport
167and
168.Fn rresvport_af
169functions are used to obtain a socket with a privileged
170address bound to it.
171This socket is suitable for use by
172.Fn rcmd
173and several other functions.
174Privileged Internet ports are those in the range 0 to
175.Va IPPORT_RESERVED - 1 ,
176which happens to be 1023.
177Only the superuser is allowed to bind an address of this sort to a socket.
178.Fn rresvport
179and
180.Fn rresvport_af
181need to be seeded with a port number; if that port
182is not available these functions will find another.
183.Pp
184The
185.Fn iruserok
186and
187.Fn ruserok
188functions take a remote host's IP address or name, respectively,
189two user names and a flag indicating whether the local user's
190name is that of the superuser.
191Then, if the user is
192.Em not
193the superuser, it checks the
194.Pa /etc/hosts.equiv
195file.
196If that lookup is not done, or is unsuccessful, the
197.Pa .rhosts
198in the local user's home directory is checked to see if the request for
199service is allowed.
200.Pp
201If this file does not exist, is not a regular file, is owned by anyone
202other than the user or the superuser, or is writeable by anyone other
203than the owner, the check automatically fails.
204Zero is returned if the machine name is listed in the
205.Pa hosts.equiv
206file, or the host and remote user name are found in the
207.Pa .rhosts
208file; otherwise
209.Fn iruserok
210and
211.Fn ruserok
212return \-1.
213If the local domain (as obtained from
214.Xr gethostname 3 )
215is the same as the remote domain, only the machine name need be specified.
216.Pp
217If the IP address of the remote host is known,
218.Fn iruserok
219should be used in preference to
220.Fn ruserok ,
221as it does not require trusting the DNS server for the remote host's domain.
222.Pp
223While
224.Fn iruserok
225can handle IPv4 addresses only,
226.Fn iruserok_sa
227and
228.Fn ruserok
229can handle other address families as well, like IPv6.
230The first argument of
231.Fn iruserok_sa
232is typed as
233.Li "void *"
234to avoid dependency between
235.Aq Pa unistd.h
236and
237.Aq Pa sys/socket.h .
238.Sh DIAGNOSTICS
239The
240.Fn rcmd
241function returns a valid socket descriptor on success.
242It returns \-1 on error and prints a diagnostic message on the standard error.
243.Pp
244The
245.Fn rresvport
246and
247.Fn rresvport_af
248functions return a valid, bound socket descriptor on success.
249It returns \-1 on error with the global value
250.Va errno
251set according to the reason for failure.
252The error code
253.Er EAGAIN
254is overloaded to mean
255.Dq all network ports in use .
256.Sh SEE ALSO
257.Xr rsh 1 ,
258.Xr intro 2 ,
259.Xr bindresvport 3 ,
260.Xr bindresvport_sa 3 ,
261.Xr rcmdsh 3 ,
262.Xr rshd 8
263.Sh HISTORY
264These
265functions appeared in
266.Bx 4.2 .
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
new file mode 100644
index 0000000000..bfe8c3ae56
--- /dev/null
+++ b/src/lib/libc/net/rcmd.c
@@ -0,0 +1,691 @@
1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
3 * Copyright (c) 1983, 1993, 1994
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#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: rcmd.c,v 1.52 2005/03/25 13:24:12 otto Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42#include <signal.h>
43#include <fcntl.h>
44#include <netdb.h>
45#include <unistd.h>
46#include <pwd.h>
47#include <errno.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <string.h>
51#include <syslog.h>
52#include <stdlib.h>
53#include <netgroup.h>
54
55int __ivaliduser(FILE *, in_addr_t, const char *, const char *);
56int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
57 const char *, const char *);
58static int __icheckhost(struct sockaddr *, socklen_t, const char *);
59static char *__gethostloop(struct sockaddr *, socklen_t);
60
61int
62rcmd(char **ahost, int rport, const char *locuser, const char *remuser,
63 const char *cmd, int *fd2p)
64{
65 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
66}
67
68int
69rcmd_af(char **ahost, int porta, const char *locuser, const char *remuser,
70 const char *cmd, int *fd2p, int af)
71{
72 static char hbuf[MAXHOSTNAMELEN];
73 char pbuf[NI_MAXSERV];
74 struct addrinfo hints, *res, *r;
75 int error;
76 struct sockaddr_storage from;
77 fd_set *readsp = NULL;
78 sigset_t oldmask, mask;
79 pid_t pid;
80 int s, lport, timo;
81 char c, *p;
82 int refused;
83 in_port_t rport = porta;
84
85 /* call rcmdsh() with specified remote shell if appropriate. */
86 if (!issetugid() && (p = getenv("RSH")) && *p) {
87 struct servent *sp = getservbyname("shell", "tcp");
88
89 if (sp && sp->s_port == rport)
90 return (rcmdsh(ahost, rport, locuser, remuser,
91 cmd, p));
92 }
93
94 /* use rsh(1) if non-root and remote port is shell. */
95 if (geteuid()) {
96 struct servent *sp = getservbyname("shell", "tcp");
97
98 if (sp && sp->s_port == rport)
99 return (rcmdsh(ahost, rport, locuser, remuser,
100 cmd, NULL));
101 }
102
103 pid = getpid();
104 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
105 memset(&hints, 0, sizeof(hints));
106 hints.ai_family = af;
107 hints.ai_socktype = SOCK_STREAM;
108 hints.ai_flags = AI_CANONNAME;
109 error = getaddrinfo(*ahost, pbuf, &hints, &res);
110 if (error) {
111#if 0
112 warnx("%s: %s", *ahost, gai_strerror(error));
113#endif
114 return (-1);
115 }
116 if (res->ai_canonname) {
117 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
118 *ahost = hbuf;
119 } else
120 ; /*XXX*/
121
122 r = res;
123 refused = 0;
124 sigemptyset(&mask);
125 sigaddset(&mask, SIGURG);
126 oldmask = sigprocmask(SIG_BLOCK, &mask, &oldmask);
127 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
128 s = rresvport_af(&lport, r->ai_family);
129 if (s < 0) {
130 if (errno == EAGAIN)
131 (void)fprintf(stderr,
132 "rcmd: socket: All ports in use\n");
133 else
134 (void)fprintf(stderr, "rcmd: socket: %s\n",
135 strerror(errno));
136 if (r->ai_next) {
137 r = r->ai_next;
138 continue;
139 } else {
140 sigprocmask(SIG_SETMASK, &oldmask, NULL);
141 freeaddrinfo(res);
142 return (-1);
143 }
144 }
145 fcntl(s, F_SETOWN, pid);
146 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
147 break;
148 (void)close(s);
149 if (errno == EADDRINUSE) {
150 lport--;
151 continue;
152 }
153 if (errno == ECONNREFUSED)
154 refused++;
155 if (r->ai_next) {
156 int oerrno = errno;
157 char hbuf[NI_MAXHOST];
158 const int niflags = NI_NUMERICHOST;
159
160 hbuf[0] = '\0';
161 if (getnameinfo(r->ai_addr, r->ai_addrlen,
162 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
163 strlcpy(hbuf, "(invalid)", sizeof hbuf);
164 (void)fprintf(stderr, "connect to address %s: ", hbuf);
165 errno = oerrno;
166 perror(0);
167 r = r->ai_next;
168 hbuf[0] = '\0';
169 if (getnameinfo(r->ai_addr, r->ai_addrlen,
170 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
171 strlcpy(hbuf, "(invalid)", sizeof hbuf);
172 (void)fprintf(stderr, "Trying %s...\n", hbuf);
173 continue;
174 }
175 if (refused && timo <= 16) {
176 (void)sleep(timo);
177 timo *= 2;
178 r = res;
179 refused = 0;
180 continue;
181 }
182 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
183 strerror(errno));
184 sigprocmask(SIG_SETMASK, &oldmask, NULL);
185 freeaddrinfo(res);
186 return (-1);
187 }
188 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
189 af = r->ai_family;
190 freeaddrinfo(res);
191#if 0
192 /*
193 * try to rresvport() to the same port. This will make rresvport()
194 * fail it's first bind, resulting in it choosing a random port.
195 */
196 lport--;
197#endif
198 if (fd2p == 0) {
199 write(s, "", 1);
200 lport = 0;
201 } else {
202 char num[8];
203 int s2 = rresvport_af(&lport, af), s3;
204 socklen_t len = sizeof(from);
205 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
206
207 if (s2 < 0)
208 goto bad;
209 readsp = (fd_set *)malloc(fdssize);
210 if (readsp == NULL) {
211 close(s2);
212 goto bad;
213 }
214 listen(s2, 1);
215 (void)snprintf(num, sizeof(num), "%d", lport);
216 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
217 (void)fprintf(stderr,
218 "rcmd: write (setting up stderr): %s\n",
219 strerror(errno));
220 (void)close(s2);
221 goto bad;
222 }
223again:
224 bzero(readsp, fdssize);
225 FD_SET(s, readsp);
226 FD_SET(s2, readsp);
227 errno = 0;
228 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
229 !FD_ISSET(s2, readsp)) {
230 if (errno != 0)
231 (void)fprintf(stderr,
232 "rcmd: select (setting up stderr): %s\n",
233 strerror(errno));
234 else
235 (void)fprintf(stderr,
236 "select: protocol failure in circuit setup\n");
237 (void)close(s2);
238 goto bad;
239 }
240 s3 = accept(s2, (struct sockaddr *)&from, &len);
241 if (s3 < 0) {
242 (void)fprintf(stderr,
243 "rcmd: accept: %s\n", strerror(errno));
244 lport = 0;
245 close(s2);
246 goto bad;
247 }
248
249 /*
250 * XXX careful for ftp bounce attacks. If discovered, shut them
251 * down and check for the real auxiliary channel to connect.
252 */
253 switch (from.ss_family) {
254 case AF_INET:
255 case AF_INET6:
256 if (getnameinfo((struct sockaddr *)&from, len,
257 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
258 atoi(num) != 20) {
259 break;
260 }
261 close(s3);
262 goto again;
263 default:
264 break;
265 }
266 (void)close(s2);
267
268 *fd2p = s3;
269 switch (from.ss_family) {
270 case AF_INET:
271 case AF_INET6:
272 if (getnameinfo((struct sockaddr *)&from, len,
273 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
274 (atoi(num) >= IPPORT_RESERVED ||
275 atoi(num) < IPPORT_RESERVED / 2)) {
276 (void)fprintf(stderr,
277 "socket: protocol failure in circuit setup.\n");
278 goto bad2;
279 }
280 break;
281 default:
282 break;
283 }
284 }
285 (void)write(s, locuser, strlen(locuser)+1);
286 (void)write(s, remuser, strlen(remuser)+1);
287 (void)write(s, cmd, strlen(cmd)+1);
288 if (read(s, &c, 1) != 1) {
289 (void)fprintf(stderr,
290 "rcmd: %s: %s\n", *ahost, strerror(errno));
291 goto bad2;
292 }
293 if (c != 0) {
294 while (read(s, &c, 1) == 1) {
295 (void)write(STDERR_FILENO, &c, 1);
296 if (c == '\n')
297 break;
298 }
299 goto bad2;
300 }
301 sigprocmask(SIG_SETMASK, &oldmask, NULL);
302 free(readsp);
303 return (s);
304bad2:
305 if (lport)
306 (void)close(*fd2p);
307bad:
308 if (readsp)
309 free(readsp);
310 (void)close(s);
311 sigprocmask(SIG_SETMASK, &oldmask, NULL);
312 return (-1);
313}
314
315int __check_rhosts_file = 1;
316char *__rcmd_errstr;
317
318int
319ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
320{
321 struct addrinfo hints, *res, *r;
322 int error;
323
324 memset(&hints, 0, sizeof(hints));
325 hints.ai_family = PF_UNSPEC;
326 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
327 error = getaddrinfo(rhost, "0", &hints, &res);
328 if (error)
329 return (-1);
330
331 for (r = res; r; r = r->ai_next) {
332 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
333 luser) == 0) {
334 freeaddrinfo(res);
335 return (0);
336 }
337 }
338 freeaddrinfo(res);
339 return (-1);
340}
341
342/*
343 * New .rhosts strategy: We are passed an ip address. We spin through
344 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
345 * has ip addresses, we don't have to trust a nameserver. When it
346 * contains hostnames, we spin through the list of addresses the nameserver
347 * gives us and look for a match.
348 *
349 * Returns 0 if ok, -1 if not ok.
350 */
351int
352iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser)
353{
354 struct sockaddr_in sin;
355
356 memset(&sin, 0, sizeof(sin));
357 sin.sin_family = AF_INET;
358 sin.sin_len = sizeof(struct sockaddr_in);
359 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
360 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
361 luser);
362}
363
364int
365iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
366 const char *luser)
367{
368 struct sockaddr *sa;
369 char *cp;
370 struct stat sbuf;
371 struct passwd *pwd;
372 FILE *hostf;
373 uid_t uid;
374 int first;
375 char pbuf[MAXPATHLEN];
376
377 sa = (struct sockaddr *)raddr;
378 first = 1;
379 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
380again:
381 if (hostf) {
382 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
383 (void)fclose(hostf);
384 return (0);
385 }
386 (void)fclose(hostf);
387 }
388 if (first == 1 && (__check_rhosts_file || superuser)) {
389 first = 0;
390 if ((pwd = getpwnam(luser)) == NULL)
391 return (-1);
392 snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
393
394 /*
395 * Change effective uid while opening .rhosts. If root and
396 * reading an NFS mounted file system, can't read files that
397 * are protected read/write owner only.
398 */
399 uid = geteuid();
400 (void)seteuid(pwd->pw_uid);
401 hostf = fopen(pbuf, "r");
402 (void)seteuid(uid);
403
404 if (hostf == NULL)
405 return (-1);
406 /*
407 * If not a regular file, or is owned by someone other than
408 * user or root or if writeable by anyone but the owner, quit.
409 */
410 cp = NULL;
411 if (lstat(pbuf, &sbuf) < 0)
412 cp = ".rhosts lstat failed";
413 else if (!S_ISREG(sbuf.st_mode))
414 cp = ".rhosts not regular file";
415 else if (fstat(fileno(hostf), &sbuf) < 0)
416 cp = ".rhosts fstat failed";
417 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
418 cp = "bad .rhosts owner";
419 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
420 cp = ".rhosts writable by other than owner";
421 /* If there were any problems, quit. */
422 if (cp) {
423 __rcmd_errstr = cp;
424 (void)fclose(hostf);
425 return (-1);
426 }
427 goto again;
428 }
429 return (-1);
430}
431
432/*
433 * XXX
434 * Don't make static, used by lpd(8).
435 *
436 * Returns 0 if ok, -1 if not ok.
437 */
438int
439__ivaliduser(FILE *hostf, in_addr_t raddrl, const char *luser,
440 const char *ruser)
441{
442 struct sockaddr_in sin;
443
444 memset(&sin, 0, sizeof(sin));
445 sin.sin_family = AF_INET;
446 sin.sin_len = sizeof(struct sockaddr_in);
447 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
448 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
449 luser, ruser);
450}
451
452int
453__ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen,
454 const char *luser, const char *ruser)
455{
456 char *user, *p;
457 char *buf;
458 const char *auser, *ahost;
459 int hostok, userok;
460 char *rhost = (char *)-1;
461 char domain[MAXHOSTNAMELEN];
462 size_t buflen;
463
464 getdomainname(domain, sizeof(domain));
465
466 while ((buf = fgetln(hostf, &buflen))) {
467 p = buf;
468 if (*p == '#')
469 continue;
470 while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') {
471 if (!isprint(*p))
472 goto bail;
473 *p = isupper(*p) ? tolower(*p) : *p;
474 p++;
475 }
476 if (p >= buf + buflen)
477 continue;
478 if (*p == ' ' || *p == '\t') {
479 *p++ = '\0';
480 while (p < buf + buflen && (*p == ' ' || *p == '\t'))
481 p++;
482 if (p >= buf + buflen)
483 continue;
484 user = p;
485 while (p < buf + buflen && *p != '\n' && *p != ' ' &&
486 *p != '\t') {
487 if (!isprint(*p))
488 goto bail;
489 p++;
490 }
491 } else
492 user = p;
493 *p = '\0';
494
495 if (p == buf)
496 continue;
497
498 auser = *user ? user : luser;
499 ahost = buf;
500
501 if (strlen(ahost) >= MAXHOSTNAMELEN)
502 continue;
503
504 /*
505 * innetgr() must lookup a hostname (we do not attempt
506 * to change the semantics so that netgroups may have
507 * #.#.#.# addresses in the list.)
508 */
509 if (ahost[0] == '+')
510 switch (ahost[1]) {
511 case '\0':
512 hostok = 1;
513 break;
514 case '@':
515 if (rhost == (char *)-1)
516 rhost = __gethostloop(raddr, salen);
517 hostok = 0;
518 if (rhost)
519 hostok = innetgr(&ahost[2], rhost,
520 NULL, domain);
521 break;
522 default:
523 hostok = __icheckhost(raddr, salen, &ahost[1]);
524 break;
525 }
526 else if (ahost[0] == '-')
527 switch (ahost[1]) {
528 case '\0':
529 hostok = -1;
530 break;
531 case '@':
532 if (rhost == (char *)-1)
533 rhost = __gethostloop(raddr, salen);
534 hostok = 0;
535 if (rhost)
536 hostok = -innetgr(&ahost[2], rhost,
537 NULL, domain);
538 break;
539 default:
540 hostok = -__icheckhost(raddr, salen, &ahost[1]);
541 break;
542 }
543 else
544 hostok = __icheckhost(raddr, salen, ahost);
545
546
547 if (auser[0] == '+')
548 switch (auser[1]) {
549 case '\0':
550 userok = 1;
551 break;
552 case '@':
553 userok = innetgr(&auser[2], NULL, ruser,
554 domain);
555 break;
556 default:
557 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
558 break;
559 }
560 else if (auser[0] == '-')
561 switch (auser[1]) {
562 case '\0':
563 userok = -1;
564 break;
565 case '@':
566 userok = -innetgr(&auser[2], NULL, ruser,
567 domain);
568 break;
569 default:
570 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
571 break;
572 }
573 else
574 userok = strcmp(ruser, auser) ? 0 : 1;
575
576 /* Check if one component did not match */
577 if (hostok == 0 || userok == 0)
578 continue;
579
580 /* Check if we got a forbidden pair */
581 if (userok <= -1 || hostok <= -1)
582 return (-1);
583
584 /* Check if we got a valid pair */
585 if (hostok >= 1 && userok >= 1)
586 return (0);
587 }
588bail:
589 return (-1);
590}
591
592/*
593 * Returns "true" if match, 0 if no match. If we do not find any
594 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
595 */
596static int
597__icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost)
598{
599 struct addrinfo hints, *res, *r;
600 char h1[NI_MAXHOST], h2[NI_MAXHOST];
601 int error;
602 const int niflags = NI_NUMERICHOST;
603
604 h1[0] = '\0';
605 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
606 niflags) != 0)
607 return (0);
608
609 /* Resolve laddr into sockaddr */
610 memset(&hints, 0, sizeof(hints));
611 hints.ai_family = raddr->sa_family;
612 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
613 res = NULL;
614 error = getaddrinfo(lhost, "0", &hints, &res);
615 if (error)
616 return (0);
617
618 /*
619 * Try string comparisons between raddr and laddr.
620 */
621 for (r = res; r; r = r->ai_next) {
622 h2[0] = '\0';
623 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
624 NULL, 0, niflags) != 0)
625 continue;
626 if (strcmp(h1, h2) == 0) {
627 freeaddrinfo(res);
628 return (1);
629 }
630 }
631
632 /* No match. */
633 freeaddrinfo(res);
634 return (0);
635}
636
637/*
638 * Return the hostname associated with the supplied address.
639 * Do a reverse lookup as well for security. If a loop cannot
640 * be found, pack the result of inet_ntoa() into the string.
641 */
642static char *
643__gethostloop(struct sockaddr *raddr, socklen_t salen)
644{
645 static char remotehost[NI_MAXHOST];
646 char h1[NI_MAXHOST], h2[NI_MAXHOST];
647 struct addrinfo hints, *res, *r;
648 int error;
649 const int niflags = NI_NUMERICHOST;
650
651 h1[0] = remotehost[0] = '\0';
652 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
653 NULL, 0, NI_NAMEREQD) != 0)
654 return (NULL);
655 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
656 niflags) != 0)
657 return (NULL);
658
659 /*
660 * Look up the name and check that the supplied
661 * address is in the list
662 */
663 memset(&hints, 0, sizeof(hints));
664 hints.ai_family = raddr->sa_family;
665 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
666 hints.ai_flags = AI_CANONNAME;
667 res = NULL;
668 error = getaddrinfo(remotehost, "0", &hints, &res);
669 if (error)
670 return (NULL);
671
672 for (r = res; r; r = r->ai_next) {
673 h2[0] = '\0';
674 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
675 NULL, 0, niflags) != 0)
676 continue;
677 if (strcmp(h1, h2) == 0) {
678 freeaddrinfo(res);
679 return (remotehost);
680 }
681 }
682
683 /*
684 * either the DNS adminstrator has made a configuration
685 * mistake, or someone has attempted to spoof us
686 */
687 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
688 h1, res->ai_canonname ? res->ai_canonname : remotehost);
689 freeaddrinfo(res);
690 return (NULL);
691}
diff --git a/src/lib/libc/net/rcmdsh.3 b/src/lib/libc/net/rcmdsh.3
new file mode 100644
index 0000000000..be566f09ca
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.3
@@ -0,0 +1,96 @@
1.\" $OpenBSD: rcmdsh.3,v 1.11 2003/06/02 20:18:35 millert Exp $
2.\"
3.\" Copyright (c) 1983, 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 May 5, 2003
31.Dt RCMDSH 3
32.Os
33.Sh NAME
34.Nm rcmdsh
35.Nd return a stream to a remote command without superuser
36.Sh SYNOPSIS
37.Fd #include <unistd.h>
38.Ft int
39.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
40.Sh DESCRIPTION
41The
42.Fn rcmdsh
43function is used by normal users to execute a command on a remote machine
44using an authentication scheme based on reserved port numbers using
45.Xr rsh 1
46or the value of
47.Fa rshprog
48(if non-null).
49.Fa rshprog
50may be a fully-qualified path, a non-qualified command, or a command containing
51space-separated command line arguments.
52.Pp
53The
54.Fn rcmdsh
55function looks up the host
56.Fa *ahost
57using
58.Xr gethostbyname 3 ,
59returning \-1 if the host does not exist.
60Otherwise
61.Fa *ahost
62is set to the standard name of the host and a connection is established to
63a server residing at the well-known Internet port
64.Li shell/tcp
65(or whatever port is used by
66.Fa rshprog ) .
67The parameter
68.Fa inport
69is ignored; it is only included to provide an interface similar to
70.Xr rcmd 3 .
71.Pp
72If the connection succeeds, a socket in the
73.Tn UNIX
74domain of type
75.Dv SOCK_STREAM
76is returned to the caller, and given to the remote
77command as stdin and stdout, and stderr.
78.Sh DIAGNOSTICS
79The
80.Fn rcmdsh
81function returns a valid socket descriptor on success.
82It returns \-1 on error and prints a diagnostic message on the standard error.
83.Sh SEE ALSO
84.Xr rsh 1 ,
85.Xr socketpair 2 ,
86.Xr rcmd 3 ,
87.Xr rshd 8
88.Sh HISTORY
89The
90.Fn rcmdsh
91function first appeared in
92.Ox 2.0 .
93.Sh BUGS
94If
95.Xr rsh 1
96encounters an error, a file descriptor is still returned instead of \-1.
diff --git a/src/lib/libc/net/rcmdsh.c b/src/lib/libc/net/rcmdsh.c
new file mode 100644
index 0000000000..28f0ca88a6
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,190 @@
1/* $OpenBSD: rcmdsh.c,v 1.10 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (c) 2001, MagniComp
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
14 * the documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the MagniComp nor the names of its contributors may
16 * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND 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 FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * This is an rcmd() replacement originally by
33 * Chris Siebenmann <cks@utcc.utoronto.ca>.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rcmdsh.c,v 1.10 2005/03/25 13:24:12 otto Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/wait.h>
43#include <signal.h>
44#include <errno.h>
45#include <netdb.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <pwd.h>
50#include <paths.h>
51#include <unistd.h>
52
53/*
54 * This is a replacement rcmd() function that uses the rsh(1)
55 * program in place of a direct rcmd(3) function call so as to
56 * avoid having to be root. Note that rport is ignored.
57 */
58/* ARGSUSED */
59int
60rcmdsh(char **ahost, int rport, const char *locuser, const char *remuser,
61 const char *cmd, char *rshprog)
62{
63 struct hostent *hp;
64 int sp[2];
65 pid_t cpid;
66 char *p;
67 struct passwd *pw;
68
69 /* What rsh/shell to use. */
70 if (rshprog == NULL)
71 rshprog = _PATH_RSH;
72
73 /* locuser must exist on this host. */
74 if ((pw = getpwnam(locuser)) == NULL) {
75 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
76 return(-1);
77 }
78
79 /* Validate remote hostname. */
80 if (strcmp(*ahost, "localhost") != 0) {
81 if (((hp = gethostbyname2(*ahost, AF_INET)) == NULL) &&
82 ((hp = gethostbyname2(*ahost, AF_INET6)) == NULL)) {
83 herror(*ahost);
84 return(-1);
85 }
86 *ahost = hp->h_name;
87 }
88
89 /* Get a socketpair we'll use for stdin and stdout. */
90 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
91 perror("rcmdsh: socketpair");
92 return(-1);
93 }
94
95 cpid = fork();
96 if (cpid < 0) {
97 perror("rcmdsh: fork failed");
98 return(-1);
99 } else if (cpid == 0) {
100 /*
101 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
102 */
103 (void) close(sp[0]);
104 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
105 perror("rcmdsh: dup2 failed");
106 _exit(255);
107 }
108 /* Fork again to lose parent. */
109 cpid = fork();
110 if (cpid < 0) {
111 perror("rcmdsh: fork to lose parent failed");
112 _exit(255);
113 }
114 if (cpid > 0)
115 _exit(0);
116
117 /* In grandchild here. Become local user for rshprog. */
118 if (setuid(pw->pw_uid)) {
119 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
120 pw->pw_uid, strerror(errno));
121 _exit(255);
122 }
123
124 /*
125 * If remote host is "localhost" and local and remote user
126 * are the same, avoid running remote shell for efficiency.
127 */
128 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
129 char *argv[4];
130 if (pw->pw_shell[0] == '\0')
131 rshprog = _PATH_BSHELL;
132 else
133 rshprog = pw->pw_shell;
134 p = strrchr(rshprog, '/');
135 argv[0] = p ? p + 1 : rshprog;
136 argv[1] = "-c";
137 argv[2] = (char *)cmd;
138 argv[3] = NULL;
139 execvp(rshprog, argv);
140 } else if ((p = strchr(rshprog, ' ')) == NULL) {
141 /* simple case */
142 char *argv[6];
143 p = strrchr(rshprog, '/');
144 argv[0] = p ? p + 1 : rshprog;
145 argv[1] = "-l";
146 argv[2] = (char *)remuser;
147 argv[3] = *ahost;
148 argv[4] = (char *)cmd;
149 argv[5] = NULL;
150 execvp(rshprog, argv);
151 } else {
152 /* must pull args out of rshprog and dyn alloc argv */
153 char **argv, **ap;
154 int n;
155 for (n = 7; (p = strchr(++p, ' ')) != NULL; n++)
156 continue;
157 rshprog = strdup(rshprog);
158 ap = argv = malloc(sizeof(char *) * n);
159 if (rshprog == NULL || argv == NULL) {
160 perror("rcmdsh");
161 _exit(255);
162 }
163 while ((p = strsep(&rshprog, " ")) != NULL) {
164 if (*p == '\0')
165 continue;
166 *ap++ = p;
167 }
168 if (ap != argv) /* all spaces?!? */
169 rshprog = argv[0];
170 if ((p = strrchr(argv[0], '/')) != NULL)
171 argv[0] = p + 1;
172 *ap++ = "-l";
173 *ap++ = (char *)remuser;
174 *ap++ = *ahost;
175 *ap++ = (char *)cmd;
176 *ap++ = NULL;
177 execvp(rshprog, argv);
178 }
179 (void) fprintf(stderr, "rcmdsh: execvp %s failed: %s\n",
180 rshprog, strerror(errno));
181 _exit(255);
182 } else {
183 /* Parent. close sp[1], return sp[0]. */
184 (void) close(sp[1]);
185 /* Reap child. */
186 (void) wait(NULL);
187 return(sp[0]);
188 }
189 /* NOTREACHED */
190}
diff --git a/src/lib/libc/net/recv.c b/src/lib/libc/net/recv.c
new file mode 100644
index 0000000000..981b5e7a6a
--- /dev/null
+++ b/src/lib/libc/net/recv.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: recv.c,v 1.4 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <stddef.h>
38
39ssize_t
40recv(int s, void *buf, size_t len, int flags)
41{
42 return (recvfrom(s, buf, len, flags, NULL, 0));
43}
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
new file mode 100644
index 0000000000..62c04d8518
--- /dev/null
+++ b/src/lib/libc/net/res_comp.c
@@ -0,0 +1,483 @@
1/* $OpenBSD: res_comp.c,v 1.12 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1993
5 * -
6 * Copyright (c) 1985, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_comp.c,v 1.12 2005/03/25 13:24:12 otto Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/nameser.h>
67
68#include <stdio.h>
69#include <resolv.h>
70#include <ctype.h>
71
72#include <unistd.h>
73#include <string.h>
74
75static int dn_find(u_char *, u_char *, u_char **, u_char **);
76
77/*
78 * Expand compressed domain name 'comp_dn' to full domain name.
79 * 'msg' is a pointer to the begining of the message,
80 * 'eomorig' points to the first location after the message,
81 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
82 * Return size of compressed name or -1 if there was an error.
83 */
84int
85dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn,
86 char *exp_dn, int length)
87{
88 const u_char *cp;
89 char *dn;
90 int n, c;
91 char *eom;
92 int len = -1, checked = 0;
93
94 dn = exp_dn;
95 cp = comp_dn;
96 if (length > MAXHOSTNAMELEN-1)
97 length = MAXHOSTNAMELEN-1;
98 eom = exp_dn + length;
99 /*
100 * fetch next label in domain name
101 */
102 while ((n = *cp++)) {
103 /*
104 * Check for indirection
105 */
106 switch (n & INDIR_MASK) {
107 case 0:
108 if (dn != exp_dn) {
109 if (dn >= eom)
110 return (-1);
111 *dn++ = '.';
112 }
113 if (dn+n >= eom)
114 return (-1);
115 checked += n + 1;
116 while (--n >= 0) {
117 if (((c = *cp++) == '.') || (c == '\\')) {
118 if (dn + n + 2 >= eom)
119 return (-1);
120 *dn++ = '\\';
121 }
122 *dn++ = c;
123 if (cp >= eomorig) /* out of range */
124 return (-1);
125 }
126 break;
127
128 case INDIR_MASK:
129 if (len < 0)
130 len = cp - comp_dn + 1;
131 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
132 if (cp < msg || cp >= eomorig) /* out of range */
133 return (-1);
134 checked += 2;
135 /*
136 * Check for loops in the compressed name;
137 * if we've looked at the whole message,
138 * there must be a loop.
139 */
140 if (checked >= eomorig - msg)
141 return (-1);
142 break;
143
144 default:
145 return (-1); /* flag error */
146 }
147 }
148 *dn = '\0';
149 if (len < 0)
150 len = cp - comp_dn;
151 return (len);
152}
153
154/*
155 * Compress domain name 'exp_dn' into 'comp_dn'.
156 * Return the size of the compressed name or -1.
157 * 'length' is the size of the array pointed to by 'comp_dn'.
158 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
159 * is a pointer to the beginning of the message. The list ends with NULL.
160 * 'lastdnptr' is a pointer to the end of the arrary pointed to
161 * by 'dnptrs'. Side effect is to update the list of pointers for
162 * labels inserted into the message as we compress the name.
163 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
164 * is NULL, we don't update the list.
165 */
166int
167dn_comp(const char *exp_dn, u_char *comp_dn, int length, u_char **dnptrs,
168 u_char **lastdnptr)
169{
170 u_char *cp, *dn;
171 int c, l;
172 u_char **cpp, **lpp, *sp, *eob;
173 u_char *msg;
174
175 dn = (u_char *)exp_dn;
176 cp = comp_dn;
177 eob = cp + length;
178 lpp = cpp = NULL;
179 if (dnptrs != NULL) {
180 if ((msg = *dnptrs++) != NULL) {
181 for (cpp = dnptrs; *cpp != NULL; cpp++)
182 ;
183 lpp = cpp; /* end of list to search */
184 }
185 } else
186 msg = NULL;
187 for (c = *dn++; c != '\0'; ) {
188 /* look to see if we can use pointers */
189 if (msg != NULL) {
190 if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
191 if (cp+1 >= eob)
192 return (-1);
193 *cp++ = (l >> 8) | INDIR_MASK;
194 *cp++ = l % 256;
195 return (cp - comp_dn);
196 }
197 /* not found, save it */
198 if (lastdnptr != NULL && cpp < lastdnptr-1) {
199 *cpp++ = cp;
200 *cpp = NULL;
201 }
202 }
203 sp = cp++; /* save ptr to length byte */
204 do {
205 if (c == '.') {
206 c = *dn++;
207 break;
208 }
209 if (c == '\\') {
210 if ((c = *dn++) == '\0')
211 break;
212 }
213 if (cp >= eob) {
214 if (msg != NULL)
215 *lpp = NULL;
216 return (-1);
217 }
218 *cp++ = c;
219 } while ((c = *dn++) != '\0');
220 /* catch trailing '.'s but not '..' */
221 if ((l = cp - sp - 1) == 0 && c == '\0') {
222 cp--;
223 break;
224 }
225 if (l <= 0 || l > MAXLABEL) {
226 if (msg != NULL)
227 *lpp = NULL;
228 return (-1);
229 }
230 *sp = l;
231 }
232 if (cp >= eob) {
233 if (msg != NULL)
234 *lpp = NULL;
235 return (-1);
236 }
237 *cp++ = '\0';
238 return (cp - comp_dn);
239}
240
241/*
242 * Skip over a compressed domain name. Return the size or -1.
243 */
244int
245__dn_skipname(const u_char *comp_dn, const u_char *eom)
246{
247 const u_char *cp;
248 int n;
249
250 cp = comp_dn;
251 while (cp < eom && (n = *cp++)) {
252 /*
253 * check for indirection
254 */
255 switch (n & INDIR_MASK) {
256 case 0: /* normal case, n == len */
257 cp += n;
258 continue;
259 case INDIR_MASK: /* indirection */
260 cp++;
261 break;
262 default: /* illegal type */
263 return (-1);
264 }
265 break;
266 }
267 if (cp > eom)
268 return (-1);
269 return (cp - comp_dn);
270}
271
272static int
273mklower(int ch)
274{
275 if (isascii(ch) && isupper(ch))
276 return (tolower(ch));
277 return (ch);
278}
279
280/*
281 * Search for expanded name from a list of previously compressed names.
282 * Return the offset from msg if found or -1.
283 * dnptrs is the pointer to the first name on the list,
284 * not the pointer to the start of the message.
285 */
286static int
287dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
288{
289 u_char *dn, *cp, **cpp;
290 int n;
291 u_char *sp;
292
293 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
294 dn = exp_dn;
295 sp = cp = *cpp;
296 while ((n = *cp++)) {
297 /*
298 * check for indirection
299 */
300 switch (n & INDIR_MASK) {
301 case 0: /* normal case, n == len */
302 while (--n >= 0) {
303 if (*dn == '.')
304 goto next;
305 if (*dn == '\\')
306 dn++;
307 if (mklower(*dn++) != mklower(*cp++))
308 goto next;
309 }
310 if ((n = *dn++) == '\0' && *cp == '\0')
311 return (sp - msg);
312 if (n == '.')
313 continue;
314 goto next;
315
316 case INDIR_MASK: /* indirection */
317 cp = msg + (((n & 0x3f) << 8) | *cp);
318 break;
319
320 default: /* illegal type */
321 return (-1);
322 }
323 }
324 if (*dn == '\0')
325 return (sp - msg);
326 next: ;
327 }
328 return (-1);
329}
330
331/*
332 * Verify that a domain name uses an acceptable character set.
333 */
334
335/*
336 * Note the conspicuous absence of ctype macros in these definitions. On
337 * non-ASCII hosts, we can't depend on string literals or ctype macros to
338 * tell us anything about network-format data. The rest of the BIND system
339 * is not careful about this, but for some reason, we're doing it right here.
340 */
341#define PERIOD 0x2e
342#define hyphenchar(c) ((c) == 0x2d)
343#define bslashchar(c) ((c) == 0x5c)
344#define periodchar(c) ((c) == PERIOD)
345#define asterchar(c) ((c) == 0x2a)
346#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
347 || ((c) >= 0x61 && (c) <= 0x7a))
348#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
349
350#define borderchar(c) (alphachar(c) || digitchar(c))
351#define middlechar(c) (borderchar(c) || hyphenchar(c))
352#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
353
354int
355res_hnok(const char *dn)
356{
357 int pch = PERIOD, ch = *dn++;
358
359 while (ch != '\0') {
360 int nch = *dn++;
361
362 if (periodchar(ch)) {
363 ;
364 } else if (periodchar(pch)) {
365 if (!borderchar(ch))
366 return (0);
367 } else if (periodchar(nch) || nch == '\0') {
368 if (!borderchar(ch))
369 return (0);
370 } else {
371 if (!middlechar(ch))
372 return (0);
373 }
374 pch = ch, ch = nch;
375 }
376 return (1);
377}
378
379/*
380 * hostname-like (A, MX, WKS) owners can have "*" as their first label
381 * but must otherwise be as a host name.
382 */
383int
384res_ownok(const char *dn)
385{
386 if (asterchar(dn[0])) {
387 if (periodchar(dn[1]))
388 return (res_hnok(dn+2));
389 if (dn[1] == '\0')
390 return (1);
391 }
392 return (res_hnok(dn));
393}
394
395/*
396 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
397 * label, but the rest of the name has to look like a host name.
398 */
399int
400res_mailok(const char *dn)
401{
402 int ch, escaped = 0;
403
404 /* "." is a valid missing representation */
405 if (*dn == '\0')
406 return(1);
407
408 /* otherwise <label>.<hostname> */
409 while ((ch = *dn++) != '\0') {
410 if (!domainchar(ch))
411 return (0);
412 if (!escaped && periodchar(ch))
413 break;
414 if (escaped)
415 escaped = 0;
416 else if (bslashchar(ch))
417 escaped = 1;
418 }
419 if (periodchar(ch))
420 return (res_hnok(dn));
421 return(0);
422}
423
424/*
425 * This function is quite liberal, since RFC 1034's character sets are only
426 * recommendations.
427 */
428int
429res_dnok(const char *dn)
430{
431 int ch;
432
433 while ((ch = *dn++) != '\0')
434 if (!domainchar(ch))
435 return (0);
436 return (1);
437}
438
439/*
440 * Routines to insert/extract short/long's.
441 */
442
443u_int16_t
444_getshort(const u_char *msgp)
445{
446 u_int16_t u;
447
448 GETSHORT(u, msgp);
449 return (u);
450}
451
452#ifdef NeXT
453/*
454 * nExt machines have some funky library conventions, which we must maintain.
455 */
456u_int16_t
457res_getshort(msgp)
458 const u_char *msgp;
459{
460 return (_getshort(msgp));
461}
462#endif
463
464u_int32_t
465_getlong(const u_char *msgp)
466{
467 u_int32_t u;
468
469 GETLONG(u, msgp);
470 return (u);
471}
472
473void
474__putshort(u_int16_t s, u_char *msgp)
475{
476 PUTSHORT(s, msgp);
477}
478
479void
480__putlong(u_int32_t l, u_char *msgp)
481{
482 PUTLONG(l, msgp);
483}
diff --git a/src/lib/libc/net/res_data.c b/src/lib/libc/net/res_data.c
new file mode 100644
index 0000000000..967264bcb7
--- /dev/null
+++ b/src/lib/libc/net/res_data.c
@@ -0,0 +1,113 @@
1/* $OpenBSD: res_data.c,v 1.2 2003/06/02 20:18:36 millert Exp $ */
2
3/*
4 * ++Copyright++ 1995
5 * -
6 * Copyright (c) 1995
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
57#else
58static char rcsid[] = "$OpenBSD: res_data.c,v 1.2 2003/06/02 20:18:36 millert Exp $";
59#endif
60#endif /* LIBC_SCCS and not lint */
61
62#include <sys/types.h>
63#include <sys/param.h>
64#include <sys/socket.h>
65#include <sys/time.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <arpa/nameser.h>
69
70#include <stdio.h>
71#include <ctype.h>
72#include <resolv.h>
73#include <unistd.h>
74#include <stdlib.h>
75#include <string.h>
76
77const char *_res_opcodes[] = {
78 "QUERY",
79 "IQUERY",
80 "CQUERYM",
81 "CQUERYU", /* experimental */
82 "NOTIFY", /* experimental */
83 "5",
84 "6",
85 "7",
86 "8",
87 "UPDATEA",
88 "UPDATED",
89 "UPDATEDA",
90 "UPDATEM",
91 "UPDATEMA",
92 "ZONEINIT",
93 "ZONEREF",
94};
95
96const char *_res_resultcodes[] = {
97 "NOERROR",
98 "FORMERR",
99 "SERVFAIL",
100 "NXDOMAIN",
101 "NOTIMP",
102 "REFUSED",
103 "6",
104 "7",
105 "8",
106 "9",
107 "10",
108 "11",
109 "12",
110 "13",
111 "14",
112 "NOCHANGE",
113};
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
new file mode 100644
index 0000000000..82a067c1f0
--- /dev/null
+++ b/src/lib/libc/net/res_debug.c
@@ -0,0 +1,1509 @@
1/* $OpenBSD: res_debug.c,v 1.20 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
6 * Copyright (c) 1985, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * Portions Copyright (c) 1995 by International Business Machines, Inc.
52 *
53 * International Business Machines, Inc. (hereinafter called IBM) grants
54 * permission under its copyrights to use, copy, modify, and distribute this
55 * Software with or without fee, provided that the above copyright notice and
56 * all paragraphs of this notice appear in all copies, and that the name of IBM
57 * not be used in connection with the marketing of any product incorporating
58 * the Software or modifications thereof, without specific, written prior
59 * permission.
60 *
61 * To the extent it has a right to do so, IBM grants an immunity from suit
62 * under its patents, if any, for the use, sale or manufacture of products to
63 * the extent that such products are used for performing Domain Name System
64 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
65 * granted for any product per se or for any other function of any product.
66 *
67 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
68 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
69 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
70 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
71 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
72 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
73 * --Copyright--
74 */
75
76#if defined(LIBC_SCCS) && !defined(lint)
77#if 0
78static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
79static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
80#else
81static char rcsid[] = "$OpenBSD: res_debug.c,v 1.20 2005/03/30 02:58:28 tedu Exp $";
82#endif
83#endif /* LIBC_SCCS and not lint */
84
85#include <sys/param.h>
86#include <sys/types.h>
87#include <sys/socket.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91
92#include <ctype.h>
93#include <netdb.h>
94#include <resolv.h>
95#include <stdio.h>
96#include <time.h>
97
98#include <stdlib.h>
99#include <string.h>
100
101#include "thread_private.h"
102
103extern const char *_res_opcodes[];
104extern const char *_res_resultcodes[];
105
106static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
107
108/* XXX: we should use getservbyport() instead. */
109static const char *
110dewks(int wks)
111{
112 static char nbuf[20];
113
114 switch (wks) {
115 case 5: return "rje";
116 case 7: return "echo";
117 case 9: return "discard";
118 case 11: return "systat";
119 case 13: return "daytime";
120 case 15: return "netstat";
121 case 17: return "qotd";
122 case 19: return "chargen";
123 case 20: return "ftp-data";
124 case 21: return "ftp";
125 case 23: return "telnet";
126 case 25: return "smtp";
127 case 37: return "time";
128 case 39: return "rlp";
129 case 42: return "name";
130 case 43: return "whois";
131 case 53: return "domain";
132 case 57: return "apts";
133 case 59: return "apfs";
134 case 67: return "bootps";
135 case 68: return "bootpc";
136 case 69: return "tftp";
137 case 77: return "rje";
138 case 79: return "finger";
139 case 87: return "link";
140 case 95: return "supdup";
141 case 100: return "newacct";
142 case 101: return "hostnames";
143 case 102: return "iso-tsap";
144 case 103: return "x400";
145 case 104: return "x400-snd";
146 case 105: return "csnet-ns";
147 case 109: return "pop-2";
148 case 111: return "sunrpc";
149 case 113: return "auth";
150 case 115: return "sftp";
151 case 117: return "uucp-path";
152 case 119: return "nntp";
153 case 121: return "erpc";
154 case 123: return "ntp";
155 case 133: return "statsrv";
156 case 136: return "profile";
157 case 144: return "NeWS";
158 case 161: return "snmp";
159 case 162: return "snmp-trap";
160 case 170: return "print-srv";
161 default:
162 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
163 return (nbuf);
164 }
165}
166
167/* XXX: we should use getprotobynumber() instead. */
168static const char *
169deproto(int protonum)
170{
171 static char nbuf[20];
172
173 switch (protonum) {
174 case 1: return "icmp";
175 case 2: return "igmp";
176 case 3: return "ggp";
177 case 5: return "st";
178 case 6: return "tcp";
179 case 7: return "ucl";
180 case 8: return "egp";
181 case 9: return "igp";
182 case 11: return "nvp-II";
183 case 12: return "pup";
184 case 16: return "chaos";
185 case 17: return "udp";
186 default:
187 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
188 return (nbuf);
189 }
190}
191
192static const u_char *
193do_rrset(const u_char *msg, int len, const u_char *cp, int cnt, int pflag,
194 FILE *file, const char *hs)
195{
196 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
197 int n;
198 int sflag;
199
200 /*
201 * Print answer records.
202 */
203 sflag = (_resp->pfcode & pflag);
204 if ((n = ntohs(cnt))) {
205 if ((!_resp->pfcode) ||
206 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
207 fprintf(file, "%s", hs);
208 while (--n >= 0) {
209 if ((!_resp->pfcode) || sflag) {
210 cp = p_rr(cp, msg, file);
211 } else {
212 unsigned int dlen;
213 cp += __dn_skipname(cp, cp + MAXCDNAME);
214 cp += INT16SZ;
215 cp += INT16SZ;
216 cp += INT32SZ;
217 dlen = _getshort((u_char*)cp);
218 cp += INT16SZ;
219 cp += dlen;
220 }
221 if ((cp - msg) > len)
222 return (NULL);
223 }
224 if ((!_resp->pfcode) ||
225 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
226 putc('\n', file);
227 }
228 return (cp);
229}
230
231void
232__p_query(const u_char *msg)
233{
234 __fp_query(msg, stdout);
235}
236
237/*
238 * Print the current options.
239 * This is intended to be primarily a debugging routine.
240 */
241void
242__fp_resstat(struct __res_state *statp, FILE *file)
243{
244 u_long mask;
245
246 fprintf(file, ";; res options:");
247 if (!statp)
248 statp = &_res;
249 for (mask = 1; mask != 0; mask <<= 1)
250 if (statp->options & mask)
251 fprintf(file, " %s", p_option(mask));
252 putc('\n', file);
253}
254
255/*
256 * Print the contents of a query.
257 * This is intended to be primarily a debugging routine.
258 */
259void
260__fp_nquery(const u_char *msg, int len, FILE *file)
261{
262 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
263 const u_char *cp, *endMark;
264 const HEADER *hp;
265 int n;
266
267 if (_res_init(0) == -1)
268 return;
269
270#define TruncTest(x) if (x > endMark) goto trunc
271#define ErrorTest(x) if (x == NULL) goto error
272
273 /*
274 * Print header fields.
275 */
276 hp = (HEADER *)msg;
277 cp = msg + HFIXEDSZ;
278 endMark = msg + len;
279 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
280 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
281 _res_opcodes[hp->opcode],
282 _res_resultcodes[hp->rcode],
283 ntohs(hp->id));
284 putc('\n', file);
285 }
286 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
287 putc(';', file);
288 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
289 fprintf(file, "; flags:");
290 if (hp->qr)
291 fprintf(file, " qr");
292 if (hp->aa)
293 fprintf(file, " aa");
294 if (hp->tc)
295 fprintf(file, " tc");
296 if (hp->rd)
297 fprintf(file, " rd");
298 if (hp->ra)
299 fprintf(file, " ra");
300 if (hp->unused)
301 fprintf(file, " UNUSED-BIT-ON");
302 if (hp->ad)
303 fprintf(file, " ad");
304 if (hp->cd)
305 fprintf(file, " cd");
306 }
307 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
308 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
309 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
310 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
311 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
312 }
313 if ((!_resp->pfcode) || (_resp->pfcode &
314 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
315 putc('\n',file);
316 }
317 /*
318 * Print question records.
319 */
320 if ((n = ntohs(hp->qdcount))) {
321 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
322 fprintf(file, ";; QUESTIONS:\n");
323 while (--n >= 0) {
324 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
325 fprintf(file, ";;\t");
326 TruncTest(cp);
327 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
328 cp = p_cdnname(cp, msg, len, file);
329 else {
330 int n;
331 char name[MAXDNAME];
332
333 if ((n = dn_expand(msg, msg+len, cp, name,
334 sizeof name)) < 0)
335 cp = NULL;
336 else
337 cp += n;
338 }
339 ErrorTest(cp);
340 TruncTest(cp);
341 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
342 fprintf(file, ", type = %s",
343 __p_type(_getshort((u_char*)cp)));
344 cp += INT16SZ;
345 TruncTest(cp);
346 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
347 fprintf(file, ", class = %s\n",
348 __p_class(_getshort((u_char*)cp)));
349 cp += INT16SZ;
350 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
351 putc('\n', file);
352 }
353 }
354 /*
355 * Print authoritative answer records
356 */
357 TruncTest(cp);
358 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
359 ";; ANSWERS:\n");
360 ErrorTest(cp);
361
362 /*
363 * print name server records
364 */
365 TruncTest(cp);
366 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
367 ";; AUTHORITY RECORDS:\n");
368 ErrorTest(cp);
369
370 TruncTest(cp);
371 /*
372 * print additional records
373 */
374 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
375 ";; ADDITIONAL RECORDS:\n");
376 ErrorTest(cp);
377 return;
378 trunc:
379 fprintf(file, "\n;; ...truncated\n");
380 return;
381 error:
382 fprintf(file, "\n;; ...malformed\n");
383}
384
385void
386__fp_query(const u_char *msg, FILE *file)
387{
388 fp_nquery(msg, PACKETSZ, file);
389}
390
391const u_char *
392__p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file)
393{
394 char name[MAXDNAME];
395 int n;
396
397 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
398 return (NULL);
399 if (name[0] == '\0')
400 putc('.', file);
401 else
402 fputs(name, file);
403 return (cp + n);
404}
405
406const u_char *
407__p_cdname(const u_char *cp, const u_char *msg, FILE *file)
408{
409 return (p_cdnname(cp, msg, PACKETSZ, file));
410}
411
412
413/* Return a fully-qualified domain name from a compressed name (with
414 length supplied). */
415
416const u_char *
417__p_fqnname(const u_char *cp, const u_char *msg, int msglen, char *name, int namelen)
418{
419 int n, newlen;
420
421 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
422 return (NULL);
423 newlen = strlen(name);
424 if (newlen == 0 || name[newlen - 1] != '.') {
425 if (newlen + 1 >= namelen) /* Lack space for final dot */
426 return (NULL);
427 else
428 strlcpy(name + newlen, ".", namelen - newlen);
429 }
430 return (cp + n);
431}
432
433/* XXX: the rest of these functions need to become length-limited, too. (vix)
434 */
435
436const u_char *
437__p_fqname(const u_char *cp, const u_char *msg, FILE *file)
438{
439 char name[MAXDNAME];
440 const u_char *n;
441
442 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
443 if (n == NULL)
444 return (NULL);
445 fputs(name, file);
446 return (n);
447}
448
449/*
450 * Print resource record fields in human readable form.
451 */
452const u_char *
453__p_rr(const u_char *cp, const u_char *msg, FILE *file)
454{
455 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
456 int type, class, dlen, n, c;
457 struct in_addr inaddr;
458 const u_char *cp1, *cp2;
459 u_int32_t tmpttl, t;
460 int lcnt;
461 u_int16_t keyflags;
462 char rrname[MAXDNAME]; /* The fqdn of this RR */
463 char base64_key[MAX_KEY_BASE64];
464
465 if (_res_init(0) == -1) {
466 h_errno = NETDB_INTERNAL;
467 return (NULL);
468 }
469 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
470 if (!cp)
471 return (NULL); /* compression error */
472 fputs(rrname, file);
473
474 type = _getshort((u_char*)cp);
475 cp += INT16SZ;
476 class = _getshort((u_char*)cp);
477 cp += INT16SZ;
478 tmpttl = _getlong((u_char*)cp);
479 cp += INT32SZ;
480 dlen = _getshort((u_char*)cp);
481 cp += INT16SZ;
482 cp1 = cp;
483 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
484 fprintf(file, "\t%lu", (u_long)tmpttl);
485 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
486 fprintf(file, "\t%s", __p_class(class));
487 fprintf(file, "\t%s", __p_type(type));
488 /*
489 * Print type specific data, if appropriate
490 */
491 switch (type) {
492 case T_A:
493 switch (class) {
494 case C_IN:
495 case C_HS:
496 bcopy(cp, (char *)&inaddr, INADDRSZ);
497 if (dlen == 4) {
498 fprintf(file, "\t%s", inet_ntoa(inaddr));
499 cp += dlen;
500 } else if (dlen == 7) {
501 char *address;
502 u_char protocol;
503 in_port_t port;
504
505 address = inet_ntoa(inaddr);
506 cp += INADDRSZ;
507 protocol = *(u_char*)cp;
508 cp += sizeof (u_char);
509 port = _getshort((u_char*)cp);
510 cp += INT16SZ;
511 fprintf(file, "\t%s\t; proto %u, port %u",
512 address, protocol, port);
513 }
514 break;
515 default:
516 cp += dlen;
517 }
518 break;
519 case T_CNAME:
520 case T_MB:
521 case T_MG:
522 case T_MR:
523 case T_NS:
524 case T_PTR:
525 putc('\t', file);
526 if ((cp = p_fqname(cp, msg, file)) == NULL)
527 return (NULL);
528 break;
529
530 case T_HINFO:
531 case T_ISDN:
532 cp2 = cp + dlen;
533 (void) fputs("\t\"", file);
534 if ((n = (unsigned char) *cp++) != 0) {
535 for (c = n; c > 0 && cp < cp2; c--) {
536 if (strchr("\n\"\\", *cp))
537 (void) putc('\\', file);
538 (void) putc(*cp++, file);
539 }
540 }
541 putc('"', file);
542 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
543 (void) fputs ("\t\"", file);
544 for (c = n; c > 0 && cp < cp2; c--) {
545 if (strchr("\n\"\\", *cp))
546 (void) putc('\\', file);
547 (void) putc(*cp++, file);
548 }
549 putc('"', file);
550 } else if (type == T_HINFO) {
551 (void) fputs("\"?\"", file);
552 fprintf(file, "\n;; *** Warning *** OS-type missing");
553 }
554 break;
555
556 case T_SOA:
557 putc('\t', file);
558 if ((cp = p_fqname(cp, msg, file)) == NULL)
559 return (NULL);
560 putc(' ', file);
561 if ((cp = p_fqname(cp, msg, file)) == NULL)
562 return (NULL);
563 fputs(" (\n", file);
564 t = _getlong((u_char*)cp); cp += INT32SZ;
565 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
566 t = _getlong((u_char*)cp); cp += INT32SZ;
567 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
568 (u_long)t, __p_time(t));
569 t = _getlong((u_char*)cp); cp += INT32SZ;
570 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
571 (u_long)t, __p_time(t));
572 t = _getlong((u_char*)cp); cp += INT32SZ;
573 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
574 (u_long)t, __p_time(t));
575 t = _getlong((u_char*)cp); cp += INT32SZ;
576 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
577 (u_long)t, __p_time(t));
578 break;
579
580 case T_MX:
581 case T_AFSDB:
582 case T_RT:
583 fprintf(file, "\t%u ", _getshort((u_char*)cp));
584 cp += INT16SZ;
585 if ((cp = p_fqname(cp, msg, file)) == NULL)
586 return (NULL);
587 break;
588
589 case T_PX:
590 fprintf(file, "\t%u ", _getshort((u_char*)cp));
591 cp += INT16SZ;
592 if ((cp = p_fqname(cp, msg, file)) == NULL)
593 return (NULL);
594 putc(' ', file);
595 if ((cp = p_fqname(cp, msg, file)) == NULL)
596 return (NULL);
597 break;
598
599 case T_X25:
600 cp2 = cp + dlen;
601 (void) fputs("\t\"", file);
602 if ((n = (unsigned char) *cp++) != 0) {
603 for (c = n; c > 0 && cp < cp2; c--) {
604 if (strchr("\n\"\\", *cp))
605 (void) putc('\\', file);
606 (void) putc(*cp++, file);
607 }
608 }
609 putc('"', file);
610 break;
611
612 case T_TXT:
613 (void) putc('\t', file);
614 cp2 = cp1 + dlen;
615 while (cp < cp2) {
616 putc('"', file);
617 if ((n = (unsigned char) *cp++)) {
618 for (c = n; c > 0 && cp < cp2; c--) {
619 if (strchr("\n\"\\", *cp))
620 (void) putc('\\', file);
621 (void) putc(*cp++, file);
622 }
623 }
624 putc('"', file);
625 if (cp < cp2)
626 putc(' ', file);
627 }
628 break;
629
630 case T_NSAP:
631 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
632 cp += dlen;
633 break;
634
635 case T_AAAA: {
636 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
637
638 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
639 cp += dlen;
640 break;
641 }
642
643 case T_LOC: {
644 char t[255];
645
646 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
647 cp += dlen;
648 break;
649 }
650
651 case T_NAPTR: {
652 u_int order, preference;
653
654 order = _getshort(cp); cp += INT16SZ;
655 preference = _getshort(cp); cp += INT16SZ;
656 fprintf(file, "\t%u %u ",order, preference);
657 /* Flags */
658 n = *cp++;
659 fprintf(file,"\"%.*s\" ", (int)n, cp);
660 cp += n;
661 /* Service */
662 n = *cp++;
663 fprintf(file,"\"%.*s\" ", (int)n, cp);
664 cp += n;
665 /* Regexp */
666 n = *cp++;
667 fprintf(file,"\"%.*s\" ", (int)n, cp);
668 cp += n;
669 if ((cp = p_fqname(cp, msg, file)) == NULL)
670 return (NULL);
671 break;
672 }
673
674 case T_SRV: {
675 u_int priority, weight, port;
676
677 priority = _getshort(cp); cp += INT16SZ;
678 weight = _getshort(cp); cp += INT16SZ;
679 port = _getshort(cp); cp += INT16SZ;
680 fprintf(file, "\t%u %u %u ", priority, weight, port);
681 if ((cp = p_fqname(cp, msg, file)) == NULL)
682 return (NULL);
683 break;
684 }
685
686 case T_MINFO:
687 case T_RP:
688 putc('\t', file);
689 if ((cp = p_fqname(cp, msg, file)) == NULL)
690 return (NULL);
691 putc(' ', file);
692 if ((cp = p_fqname(cp, msg, file)) == NULL)
693 return (NULL);
694 break;
695
696 case T_UINFO:
697 putc('\t', file);
698 fputs((char *)cp, file);
699 cp += dlen;
700 break;
701
702 case T_UID:
703 case T_GID:
704 if (dlen == 4) {
705 fprintf(file, "\t%u", _getlong((u_char*)cp));
706 cp += INT32SZ;
707 }
708 break;
709
710 case T_WKS:
711 if (dlen < INT32SZ + 1)
712 break;
713 bcopy(cp, (char *)&inaddr, INADDRSZ);
714 cp += INT32SZ;
715 fprintf(file, "\t%s %s ( ",
716 inet_ntoa(inaddr),
717 deproto((int) *cp));
718 cp += sizeof (u_char);
719 n = 0;
720 lcnt = 0;
721 while (cp < cp1 + dlen) {
722 c = *cp++;
723 do {
724 if (c & 0200) {
725 if (lcnt == 0) {
726 fputs("\n\t\t\t", file);
727 lcnt = 5;
728 }
729 fputs(dewks(n), file);
730 putc(' ', file);
731 lcnt--;
732 }
733 c <<= 1;
734 } while (++n & 07);
735 }
736 putc(')', file);
737 break;
738
739 case T_KEY:
740 putc('\t', file);
741 keyflags = _getshort(cp);
742 cp += 2;
743 fprintf(file,"0x%04x", keyflags ); /* flags */
744 fprintf(file," %u", *cp++); /* protocol */
745 fprintf(file," %u (", *cp++); /* algorithm */
746
747 n = b64_ntop(cp, (cp1 + dlen) - cp,
748 base64_key, sizeof base64_key);
749 for (c = 0; c < n; ++c) {
750 if (0 == (c & 0x3F))
751 fprintf(file, "\n\t");
752 putc(base64_key[c], file); /* public key data */
753 }
754
755 fprintf(file, " )");
756 if (n < 0)
757 fprintf(file, "\t; BAD BASE64");
758 fflush(file);
759 cp = cp1 + dlen;
760 break;
761
762 case T_SIG:
763 type = _getshort((u_char*)cp);
764 cp += INT16SZ;
765 fprintf(file, " %s", p_type(type));
766 fprintf(file, "\t%u", *cp++); /* algorithm */
767 /* Check label value and print error if wrong. */
768 n = *cp++;
769 c = dn_count_labels (rrname);
770 if (n != c)
771 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
772 n, c);
773 /* orig ttl */
774 n = _getlong((u_char*)cp);
775 if (n != tmpttl)
776 fprintf(file, " %u", n);
777 cp += INT32SZ;
778 /* sig expire */
779 fprintf(file, " (\n\t%s",
780 __p_secstodate(_getlong((u_char*)cp)));
781 cp += INT32SZ;
782 /* time signed */
783 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
784 cp += INT32SZ;
785 /* sig footprint */
786 fprintf(file," %u ", _getshort((u_char*)cp));
787 cp += INT16SZ;
788 /* signer's name */
789 cp = p_fqname(cp, msg, file);
790 n = b64_ntop(cp, (cp1 + dlen) - cp,
791 base64_key, sizeof base64_key);
792 for (c = 0; c < n; c++) {
793 if (0 == (c & 0x3F))
794 fprintf (file, "\n\t");
795 putc(base64_key[c], file); /* signature */
796 }
797 /* Clean up... */
798 fprintf(file, " )");
799 if (n < 0)
800 fprintf(file, "\t; BAD BASE64");
801 fflush(file);
802 cp = cp1+dlen;
803 break;
804
805#ifdef ALLOW_T_UNSPEC
806 case T_UNSPEC:
807 {
808 int NumBytes = 8;
809 u_char *DataPtr;
810 int i;
811
812 if (dlen < NumBytes) NumBytes = dlen;
813 fprintf(file, "\tFirst %d bytes of hex data:",
814 NumBytes);
815 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
816 fprintf(file, " %x", *DataPtr);
817 cp += dlen;
818 }
819 break;
820#endif /* ALLOW_T_UNSPEC */
821
822 default:
823 fprintf(file, "\t?%d?", type);
824 cp += dlen;
825 }
826#if 0
827 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
828#else
829 putc('\n', file);
830#endif
831 if (cp - cp1 != dlen) {
832 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
833 (long)(cp - cp1), dlen);
834 cp = NULL;
835 }
836 return (cp);
837}
838
839/*
840 * Names of RR classes and qclasses. Classes and qclasses are the same, except
841 * that C_ANY is a qclass but not a class. (You can ask for records of class
842 * C_ANY, but you can't have any records of that class in the database.)
843 */
844const struct res_sym __p_class_syms[] = {
845 {C_IN, "IN"},
846 {C_CHAOS, "CHAOS"},
847 {C_HS, "HS"},
848 {C_HS, "HESIOD"},
849 {C_ANY, "ANY"},
850 {C_IN, (char *)0}
851};
852
853/*
854 * Names of RR types and qtypes. Types and qtypes are the same, except
855 * that T_ANY is a qtype but not a type. (You can ask for records of type
856 * T_ANY, but you can't have any records of that type in the database.)
857 */
858const struct res_sym __p_type_syms[] = {
859 {T_A, "A", "address"},
860 {T_NS, "NS", "name server"},
861 {T_MD, "MD", "mail destination (deprecated)"},
862 {T_MF, "MF", "mail forwarder (deprecated)"},
863 {T_CNAME, "CNAME", "canonical name"},
864 {T_SOA, "SOA", "start of authority"},
865 {T_MB, "MB", "mailbox"},
866 {T_MG, "MG", "mail group member"},
867 {T_MR, "MR", "mail rename"},
868 {T_NULL, "NULL", "null"},
869 {T_WKS, "WKS", "well-known service (deprecated)"},
870 {T_PTR, "PTR", "domain name pointer"},
871 {T_HINFO, "HINFO", "host information"},
872 {T_MINFO, "MINFO", "mailbox information"},
873 {T_MX, "MX", "mail exchanger"},
874 {T_TXT, "TXT", "text"},
875 {T_RP, "RP", "responsible person"},
876 {T_AFSDB, "AFSDB", "DCE or AFS server"},
877 {T_X25, "X25", "X25 address"},
878 {T_ISDN, "ISDN", "ISDN address"},
879 {T_RT, "RT", "router"},
880 {T_NSAP, "NSAP", "nsap address"},
881 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
882 {T_SIG, "SIG", "signature"},
883 {T_KEY, "KEY", "key"},
884 {T_PX, "PX", "mapping information"},
885 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
886 {T_AAAA, "AAAA", "IPv6 address"},
887 {T_LOC, "LOC", "location"},
888 {T_NXT, "NXT", "next valid name (unimplemented)"},
889 {T_EID, "EID", "endpoint identifier (unimplemented)"},
890 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
891 {T_SRV, "SRV", "server selection"},
892 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
893 {T_IXFR, "IXFR", "incremental zone transfer"},
894 {T_AXFR, "AXFR", "zone transfer"},
895 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
896 {T_MAILA, "MAILA", "mail agent (deprecated)"},
897 {T_UINFO, "UINFO", "user information (nonstandard)"},
898 {T_UID, "UID", "user ID (nonstandard)"},
899 {T_GID, "GID", "group ID (nonstandard)"},
900 {T_NAPTR, "NAPTR", "URN Naming Authority"},
901#ifdef ALLOW_T_UNSPEC
902 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
903#endif /* ALLOW_T_UNSPEC */
904 {T_ANY, "ANY", "\"any\""},
905 {0, NULL, NULL}
906};
907
908int
909__sym_ston(const struct res_sym *syms, char *name, int *success)
910{
911 for (; syms->name != 0; syms++) {
912 if (strcasecmp (name, syms->name) == 0) {
913 if (success)
914 *success = 1;
915 return (syms->number);
916 }
917 }
918 if (success)
919 *success = 0;
920 return (syms->number); /* The default value. */
921}
922
923const char *
924__sym_ntos(const struct res_sym *syms, int number, int *success)
925{
926 static char unname[20];
927
928 for (; syms->name != 0; syms++) {
929 if (number == syms->number) {
930 if (success)
931 *success = 1;
932 return (syms->name);
933 }
934 }
935
936 snprintf(unname, sizeof unname, "%d", number);
937 if (success)
938 *success = 0;
939 return (unname);
940}
941
942
943const char *
944__sym_ntop(const struct res_sym *syms, int number, int *success)
945{
946 static char unname[20];
947
948 for (; syms->name != 0; syms++) {
949 if (number == syms->number) {
950 if (success)
951 *success = 1;
952 return (syms->humanname);
953 }
954 }
955 snprintf(unname, sizeof unname, "%d", number);
956 if (success)
957 *success = 0;
958 return (unname);
959}
960
961/*
962 * Return a string for the type
963 */
964const char *
965__p_type(int type)
966{
967 return (__sym_ntos (__p_type_syms, type, (int *)0));
968}
969
970/*
971 * Return a mnemonic for class
972 */
973const char *
974__p_class(int class)
975{
976 return (__sym_ntos (__p_class_syms, class, (int *)0));
977}
978
979/*
980 * Return a mnemonic for an option
981 */
982const char *
983__p_option(u_long option)
984{
985 static char nbuf[40];
986
987 switch (option) {
988 case RES_INIT: return "init";
989 case RES_DEBUG: return "debug";
990 case RES_AAONLY: return "aaonly(unimpl)";
991 case RES_USEVC: return "usevc";
992 case RES_PRIMARY: return "primry(unimpl)";
993 case RES_IGNTC: return "igntc";
994 case RES_RECURSE: return "recurs";
995 case RES_DEFNAMES: return "defnam";
996 case RES_STAYOPEN: return "styopn";
997 case RES_DNSRCH: return "dnsrch";
998 case RES_INSECURE1: return "insecure1";
999 case RES_INSECURE2: return "insecure2";
1000 case RES_USE_INET6: return "inet6";
1001 case RES_USE_EDNS0: return "edns0";
1002 default:
1003 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1004 return (nbuf);
1005 }
1006}
1007
1008/*
1009 * Return a mnemonic for a time to live
1010 */
1011const char *
1012p_time(u_int32_t value)
1013{
1014 static char nbuf[40];
1015 char *ebuf;
1016 int secs, mins, hours, days;
1017 char *p;
1018 int tmp;
1019
1020 if (value == 0) {
1021 strlcpy(nbuf, "0 secs", sizeof nbuf);
1022 return (nbuf);
1023 }
1024
1025 secs = value % 60;
1026 value /= 60;
1027 mins = value % 60;
1028 value /= 60;
1029 hours = value % 24;
1030 value /= 24;
1031 days = value;
1032 value = 0;
1033
1034#define PLURALIZE(x) x, (x == 1) ? "" : "s"
1035 p = nbuf;
1036 ebuf = nbuf + sizeof(nbuf);
1037 if (days) {
1038 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
1039 PLURALIZE(days))) >= ebuf - p || tmp < 0)
1040 goto full;
1041 p += tmp;
1042 }
1043 if (hours) {
1044 if (days)
1045 *p++ = ' ';
1046 if (p >= ebuf)
1047 goto full;
1048 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1049 PLURALIZE(hours))) >= ebuf - p || tmp < 0)
1050 goto full;
1051 p += tmp;
1052 }
1053 if (mins) {
1054 if (days || hours)
1055 *p++ = ' ';
1056 if (p >= ebuf)
1057 goto full;
1058 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1059 PLURALIZE(mins))) >= ebuf - p || tmp < 0)
1060 goto full;
1061 p += tmp;
1062 }
1063 if (secs || ! (days || hours || mins)) {
1064 if (days || hours || mins)
1065 *p++ = ' ';
1066 if (p >= ebuf)
1067 goto full;
1068 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1069 PLURALIZE(secs))) >= ebuf - p || tmp < 0)
1070 goto full;
1071 }
1072 return (nbuf);
1073full:
1074 p = nbuf + sizeof(nbuf) - 4;
1075 *p++ = '.';
1076 *p++ = '.';
1077 *p++ = '.';
1078 *p++ = '\0';
1079 return (nbuf);
1080}
1081
1082/*
1083 * routines to convert between on-the-wire RR format and zone file format.
1084 * Does not contain conversion to/from decimal degrees; divide or multiply
1085 * by 60*60*1000 for that.
1086 */
1087
1088static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1089 1000000,10000000,100000000,1000000000};
1090
1091/* takes an XeY precision/size value, returns a string representation. */
1092static const char *
1093precsize_ntoa(u_int8_t prec)
1094{
1095 static char retbuf[sizeof "90000000.00"];
1096 unsigned long val;
1097 int mantissa, exponent;
1098
1099 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1100 exponent = (int)((prec >> 0) & 0x0f) % 10;
1101
1102 val = mantissa * poweroften[exponent];
1103
1104 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1105 return (retbuf);
1106}
1107
1108/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1109static u_int8_t
1110precsize_aton(char **strptr)
1111{
1112 unsigned int mval = 0, cmval = 0;
1113 u_int8_t retval = 0;
1114 char *cp;
1115 int exponent;
1116 int mantissa;
1117
1118 cp = *strptr;
1119
1120 while (isdigit(*cp))
1121 mval = mval * 10 + (*cp++ - '0');
1122
1123 if (*cp == '.') { /* centimeters */
1124 cp++;
1125 if (isdigit(*cp)) {
1126 cmval = (*cp++ - '0') * 10;
1127 if (isdigit(*cp)) {
1128 cmval += (*cp++ - '0');
1129 }
1130 }
1131 }
1132 cmval = (mval * 100) + cmval;
1133
1134 for (exponent = 0; exponent < 9; exponent++)
1135 if (cmval < poweroften[exponent+1])
1136 break;
1137
1138 mantissa = cmval / poweroften[exponent];
1139 if (mantissa > 9)
1140 mantissa = 9;
1141
1142 retval = (mantissa << 4) | exponent;
1143
1144 *strptr = cp;
1145
1146 return (retval);
1147}
1148
1149/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1150static u_int32_t
1151latlon2ul(char **latlonstrptr, int *which)
1152{
1153 char *cp;
1154 u_int32_t retval;
1155 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1156
1157 cp = *latlonstrptr;
1158
1159 while (isdigit(*cp))
1160 deg = deg * 10 + (*cp++ - '0');
1161
1162 while (isspace(*cp))
1163 cp++;
1164
1165 if (!(isdigit(*cp)))
1166 goto fndhemi;
1167
1168 while (isdigit(*cp))
1169 min = min * 10 + (*cp++ - '0');
1170
1171 while (isspace(*cp))
1172 cp++;
1173
1174 if (!(isdigit(*cp)))
1175 goto fndhemi;
1176
1177 while (isdigit(*cp))
1178 secs = secs * 10 + (*cp++ - '0');
1179
1180 if (*cp == '.') { /* decimal seconds */
1181 cp++;
1182 if (isdigit(*cp)) {
1183 secsfrac = (*cp++ - '0') * 100;
1184 if (isdigit(*cp)) {
1185 secsfrac += (*cp++ - '0') * 10;
1186 if (isdigit(*cp)) {
1187 secsfrac += (*cp++ - '0');
1188 }
1189 }
1190 }
1191 }
1192
1193 while (!isspace(*cp)) /* if any trailing garbage */
1194 cp++;
1195
1196 while (isspace(*cp))
1197 cp++;
1198
1199 fndhemi:
1200 switch (*cp) {
1201 case 'N': case 'n':
1202 case 'E': case 'e':
1203 retval = ((unsigned)1<<31)
1204 + (((((deg * 60) + min) * 60) + secs) * 1000)
1205 + secsfrac;
1206 break;
1207 case 'S': case 's':
1208 case 'W': case 'w':
1209 retval = ((unsigned)1<<31)
1210 - (((((deg * 60) + min) * 60) + secs) * 1000)
1211 - secsfrac;
1212 break;
1213 default:
1214 retval = 0; /* invalid value -- indicates error */
1215 break;
1216 }
1217
1218 switch (*cp) {
1219 case 'N': case 'n':
1220 case 'S': case 's':
1221 *which = 1; /* latitude */
1222 break;
1223 case 'E': case 'e':
1224 case 'W': case 'w':
1225 *which = 2; /* longitude */
1226 break;
1227 default:
1228 *which = 0; /* error */
1229 break;
1230 }
1231
1232 cp++; /* skip the hemisphere */
1233
1234 while (!isspace(*cp)) /* if any trailing garbage */
1235 cp++;
1236
1237 while (isspace(*cp)) /* move to next field */
1238 cp++;
1239
1240 *latlonstrptr = cp;
1241
1242 return (retval);
1243}
1244
1245/* converts a zone file representation in a string to an RDATA on-the-wire
1246 * representation. */
1247int
1248loc_aton(const char *ascii, u_char *binary)
1249{
1250 const char *maxcp;
1251 u_char *bcp;
1252 char *cp;
1253
1254 u_int32_t latit = 0, longit = 0, alt = 0;
1255 u_int32_t lltemp1 = 0, lltemp2 = 0;
1256 int altmeters = 0, altfrac = 0, altsign = 1;
1257 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1258 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1259 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1260 int which1 = 0, which2 = 0;
1261
1262 cp = (char *)ascii;
1263 maxcp = cp + strlen(ascii);
1264
1265 lltemp1 = latlon2ul(&cp, &which1);
1266
1267 lltemp2 = latlon2ul(&cp, &which2);
1268
1269 switch (which1 + which2) {
1270 case 3: /* 1 + 2, the only valid combination */
1271 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1272 latit = lltemp1;
1273 longit = lltemp2;
1274 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1275 longit = lltemp1;
1276 latit = lltemp2;
1277 } else { /* some kind of brokenness */
1278 return (0);
1279 }
1280 break;
1281 default: /* we didn't get one of each */
1282 return (0);
1283 }
1284
1285 /* altitude */
1286 if (*cp == '-') {
1287 altsign = -1;
1288 cp++;
1289 }
1290
1291 if (*cp == '+')
1292 cp++;
1293
1294 while (isdigit(*cp))
1295 altmeters = altmeters * 10 + (*cp++ - '0');
1296
1297 if (*cp == '.') { /* decimal meters */
1298 cp++;
1299 if (isdigit(*cp)) {
1300 altfrac = (*cp++ - '0') * 10;
1301 if (isdigit(*cp)) {
1302 altfrac += (*cp++ - '0');
1303 }
1304 }
1305 }
1306
1307 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1308
1309 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1310 cp++;
1311
1312 while (isspace(*cp) && (cp < maxcp))
1313 cp++;
1314
1315 if (cp >= maxcp)
1316 goto defaults;
1317
1318 siz = precsize_aton(&cp);
1319
1320 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1321 cp++;
1322
1323 while (isspace(*cp) && (cp < maxcp))
1324 cp++;
1325
1326 if (cp >= maxcp)
1327 goto defaults;
1328
1329 hp = precsize_aton(&cp);
1330
1331 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1332 cp++;
1333
1334 while (isspace(*cp) && (cp < maxcp))
1335 cp++;
1336
1337 if (cp >= maxcp)
1338 goto defaults;
1339
1340 vp = precsize_aton(&cp);
1341
1342 defaults:
1343
1344 bcp = binary;
1345 *bcp++ = (u_int8_t) 0; /* version byte */
1346 *bcp++ = siz;
1347 *bcp++ = hp;
1348 *bcp++ = vp;
1349 PUTLONG(latit,bcp);
1350 PUTLONG(longit,bcp);
1351 PUTLONG(alt,bcp);
1352
1353 return (16); /* size of RR in octets */
1354}
1355
1356const char *
1357loc_ntoa(const u_char *binary, char *ascii)
1358{
1359 return loc_ntoal(binary, ascii, 255);
1360}
1361
1362/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1363static const char *
1364loc_ntoal(const u_char *binary, char *ascii, int ascii_len)
1365{
1366 static char *error = "?";
1367 const u_char *cp = binary;
1368
1369 int latdeg, latmin, latsec, latsecfrac;
1370 int longdeg, longmin, longsec, longsecfrac;
1371 char northsouth, eastwest;
1372 int altmeters, altfrac, altsign;
1373
1374 const int referencealt = 100000 * 100;
1375
1376 int32_t latval, longval, altval;
1377 u_int32_t templ;
1378 u_int8_t sizeval, hpval, vpval, versionval;
1379
1380 char *sizestr, *hpstr, *vpstr;
1381
1382 versionval = *cp++;
1383
1384 if (versionval) {
1385 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1386 return (ascii);
1387 }
1388
1389 sizeval = *cp++;
1390
1391 hpval = *cp++;
1392 vpval = *cp++;
1393
1394 GETLONG(templ, cp);
1395 latval = (templ - ((unsigned)1<<31));
1396
1397 GETLONG(templ, cp);
1398 longval = (templ - ((unsigned)1<<31));
1399
1400 GETLONG(templ, cp);
1401 if (templ < referencealt) { /* below WGS 84 spheroid */
1402 altval = referencealt - templ;
1403 altsign = -1;
1404 } else {
1405 altval = templ - referencealt;
1406 altsign = 1;
1407 }
1408
1409 if (latval < 0) {
1410 northsouth = 'S';
1411 latval = -latval;
1412 } else
1413 northsouth = 'N';
1414
1415 latsecfrac = latval % 1000;
1416 latval = latval / 1000;
1417 latsec = latval % 60;
1418 latval = latval / 60;
1419 latmin = latval % 60;
1420 latval = latval / 60;
1421 latdeg = latval;
1422
1423 if (longval < 0) {
1424 eastwest = 'W';
1425 longval = -longval;
1426 } else
1427 eastwest = 'E';
1428
1429 longsecfrac = longval % 1000;
1430 longval = longval / 1000;
1431 longsec = longval % 60;
1432 longval = longval / 60;
1433 longmin = longval % 60;
1434 longval = longval / 60;
1435 longdeg = longval;
1436
1437 altfrac = altval % 100;
1438 altmeters = (altval / 100) * altsign;
1439
1440 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1441 sizestr = error;
1442 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1443 hpstr = error;
1444 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1445 vpstr = error;
1446
1447 snprintf(ascii, ascii_len,
1448 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1449 latdeg, latmin, latsec, latsecfrac, northsouth,
1450 longdeg, longmin, longsec, longsecfrac, eastwest,
1451 altmeters, altfrac, sizestr, hpstr, vpstr);
1452
1453 if (sizestr != error)
1454 free(sizestr);
1455 if (hpstr != error)
1456 free(hpstr);
1457 if (vpstr != error)
1458 free(vpstr);
1459
1460 return (ascii);
1461}
1462
1463
1464/* Return the number of DNS hierarchy levels in the name. */
1465int
1466__dn_count_labels(char *name)
1467{
1468 int i, len, count;
1469
1470 len = strlen(name);
1471
1472 for(i = 0, count = 0; i < len; i++) {
1473 if (name[i] == '.')
1474 count++;
1475 }
1476
1477 /* don't count initial wildcard */
1478 if (name[0] == '*')
1479 if (count)
1480 count--;
1481
1482 /* don't count the null label for root. */
1483 /* if terminating '.' not found, must adjust */
1484 /* count to include last label */
1485 if (len > 0 && name[len-1] != '.')
1486 count++;
1487 return (count);
1488}
1489
1490
1491/*
1492 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1493 * SIG records are required to be printed like this, by the Secure DNS RFC.
1494 */
1495char *
1496__p_secstodate (long unsigned int secs)
1497{
1498 static char output[15]; /* YYYYMMDDHHMMSS and null */
1499 time_t clock = secs;
1500 struct tm *time;
1501
1502 time = gmtime(&clock);
1503 time->tm_year += 1900;
1504 time->tm_mon += 1;
1505 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1506 time->tm_year, time->tm_mon, time->tm_mday,
1507 time->tm_hour, time->tm_min, time->tm_sec);
1508 return (output);
1509}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
new file mode 100644
index 0000000000..110542a404
--- /dev/null
+++ b/src/lib/libc/net/res_init.c
@@ -0,0 +1,678 @@
1/* $OpenBSD: res_init.c,v 1.32 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#ifndef INET6
55#define INET6
56#endif
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
61static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_init.c,v 1.32 2005/03/30 02:58:28 tedu Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <sys/socket.h>
70#include <sys/time.h>
71#include <sys/stat.h>
72#include <netinet/in.h>
73#include <arpa/inet.h>
74#include <arpa/nameser.h>
75
76#include <stdio.h>
77#include <ctype.h>
78#include <resolv.h>
79#include <unistd.h>
80#include <stdlib.h>
81#include <string.h>
82#ifdef INET6
83#include <netdb.h>
84#endif /* INET6 */
85
86#include "thread_private.h"
87
88/*-------------------------------------- info about "sortlist" --------------
89 * Marc Majka 1994/04/16
90 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
91 *
92 * NetInfo resolver configuration directory support.
93 *
94 * Allow a NetInfo directory to be created in the hierarchy which
95 * contains the same information as the resolver configuration file.
96 *
97 * - The local domain name is stored as the value of the "domain" property.
98 * - The Internet address(es) of the name server(s) are stored as values
99 * of the "nameserver" property.
100 * - The name server addresses are stored as values of the "nameserver"
101 * property.
102 * - The search list for host-name lookup is stored as values of the
103 * "search" property.
104 * - The sortlist comprised of IP address netmask pairs are stored as
105 * values of the "sortlist" property. The IP address and optional netmask
106 * should be separated by a slash (/) or ampersand (&) character.
107 * - Internal resolver variables can be set from the value of the "options"
108 * property.
109 */
110
111static void res_setoptions(char *, char *);
112
113#ifdef RESOLVSORT
114static const char sort_mask[] = "/&";
115#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
116static u_int32_t net_mask(struct in_addr);
117#endif
118
119/*
120 * Resolver state default settings.
121 */
122void *__THREAD_NAME(_res);
123
124struct __res_state _res
125# if defined(__BIND_RES_TEXT)
126 = { RES_TIMEOUT, } /* Motorola, et al. */
127# endif
128 ;
129#ifdef INET6
130void *__THREAD_NAME(_res_ext);
131
132struct __res_state_ext _res_ext;
133#endif /* INET6 */
134
135int __res_chktime = 30;
136
137/*
138 * Set up default settings. If the configuration file exist, the values
139 * there will have precedence. Otherwise, the server address is set to
140 * INADDR_ANY and the default domain name comes from the gethostname().
141 *
142 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
143 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
144 * since it was noted that INADDR_ANY actually meant ``the first interface
145 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
146 * it had to be "up" in order for you to reach your own name server. It
147 * was later decided that since the recommended practice is to always
148 * install local static routes through 127.0.0.1 for all your network
149 * interfaces, that we could solve this problem without a code change.
150 *
151 * The configuration file should always be used, since it is the only way
152 * to specify a default domain. If you are running a server on your local
153 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
154 * in the configuration file.
155 *
156 * Return 0 if completes successfully, -1 on error
157 */
158int
159res_init(void)
160{
161
162 return (_res_init(1));
163}
164
165int
166_res_init(int usercall)
167{
168 struct stat sb;
169 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
170#ifdef INET6
171 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
172 &_res_ext);
173#endif
174 FILE *fp;
175 char *cp, **pp;
176 int n;
177 char buf[BUFSIZ];
178 int nserv = 0; /* number of nameserver records read from file */
179 int haveenv = 0;
180 int havesearch = 0;
181 size_t len;
182#ifdef RESOLVSORT
183 int nsort = 0;
184 char *net;
185#endif
186#ifndef RFC1535
187 int dots;
188#endif
189
190 if (usercall == 0) {
191 if (_resp->options & RES_INIT &&
192 _resp->reschktime >= time(NULL))
193 return (0);
194 _resp->reschktime = time(NULL) + __res_chktime;
195 if (stat(_PATH_RESCONF, &sb) != -1) {
196 if (timespeccmp(&sb.st_mtimespec,
197 &_resp->restimespec, ==))
198 return (0);
199 else
200 _resp->restimespec = sb.st_mtimespec;
201 } else {
202 /*
203 * Lost the file, in chroot?
204 * Don' trash settings
205 */
206 if (timespecisset(&_resp->restimespec))
207 return (0);
208 }
209 } else
210 _resp->reschktime = time(NULL) + __res_chktime;
211
212
213 /*
214 * These three fields used to be statically initialized. This made
215 * it hard to use this code in a shared library. It is necessary,
216 * now that we're doing dynamic initialization here, that we preserve
217 * the old semantics: if an application modifies one of these three
218 * fields of _res before res_init() is called, res_init() will not
219 * alter them. Of course, if an application is setting them to
220 * _zero_ before calling res_init(), hoping to override what used
221 * to be the static default, we can't detect it and unexpected results
222 * will follow. Zero for any of these fields would make no sense,
223 * so one can safely assume that the applications were already getting
224 * unexpected results.
225 *
226 * _res.options is tricky since some apps were known to diddle the bits
227 * before res_init() was first called. We can't replicate that semantic
228 * with dynamic initialization (they may have turned bits off that are
229 * set in RES_DEFAULT). Our solution is to declare such applications
230 * "broken". They could fool us by setting RES_INIT but none do (yet).
231 */
232 if (!_resp->retrans)
233 _resp->retrans = RES_TIMEOUT;
234 if (!_resp->retry)
235 _resp->retry = 4;
236 if (!(_resp->options & RES_INIT))
237 _resp->options = RES_DEFAULT;
238
239#ifdef USELOOPBACK
240 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
241#else
242 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
243#endif
244 _resp->nsaddr.sin_family = AF_INET;
245 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
246 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
247#ifdef INET6
248 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
249 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
250#endif
251 _resp->nscount = 1;
252 _resp->ndots = 1;
253 _resp->pfcode = 0;
254 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
255
256 /* Allow user to override the local domain definition */
257 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
258 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
259 haveenv++;
260
261 /*
262 * Set search list to be blank-separated strings
263 * from rest of env value. Permits users of LOCALDOMAIN
264 * to still have a search list, and anyone to set the
265 * one that they want to use as an individual (even more
266 * important now that the rfc1535 stuff restricts searches)
267 */
268 cp = _resp->defdname;
269 pp = _resp->dnsrch;
270 *pp++ = cp;
271 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
272 if (*cp == '\n') /* silly backwards compat */
273 break;
274 else if (*cp == ' ' || *cp == '\t') {
275 *cp = 0;
276 n = 1;
277 } else if (n) {
278 *pp++ = cp;
279 n = 0;
280 havesearch = 1;
281 }
282 }
283 /* null terminate last domain if there are excess */
284 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
285 cp++;
286 *cp = '\0';
287 *pp++ = 0;
288 }
289
290#define MATCH(line, name) \
291 (!strncmp(line, name, sizeof(name) - 1) && \
292 (line[sizeof(name) - 1] == ' ' || \
293 line[sizeof(name) - 1] == '\t'))
294
295 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
296 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
297
298 /* read the config file */
299 buf[0] = '\0';
300 while ((cp = fgetln(fp, &len)) != NULL) {
301 /* skip lines that are too long or zero length */
302 if (len >= sizeof(buf) || len == 0)
303 continue;
304 (void)memcpy(buf, cp, len);
305 buf[len] = '\0';
306 /* skip comments */
307 if ((cp = strpbrk(buf, ";#")) != NULL)
308 *cp = '\0';
309 if (buf[0] == '\0')
310 continue;
311 /* read default domain name */
312 if (MATCH(buf, "domain")) {
313 if (haveenv) /* skip if have from environ */
314 continue;
315 cp = buf + sizeof("domain") - 1;
316 while (*cp == ' ' || *cp == '\t')
317 cp++;
318 if ((*cp == '\0') || (*cp == '\n'))
319 continue;
320 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
321 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
322 *cp = '\0';
323 havesearch = 0;
324 continue;
325 }
326 /* lookup types */
327 if (MATCH(buf, "lookup")) {
328 char *sp = NULL;
329
330 bzero(_resp->lookups, sizeof _resp->lookups);
331 cp = buf + sizeof("lookup") - 1;
332 for (n = 0;; cp++) {
333 if (n == MAXDNSLUS)
334 break;
335 if ((*cp == '\0') || (*cp == '\n')) {
336 if (sp) {
337 if (*sp=='y' || *sp=='b' || *sp=='f')
338 _resp->lookups[n++] = *sp;
339 sp = NULL;
340 }
341 break;
342 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
343 if (sp) {
344 if (*sp=='y' || *sp=='b' || *sp=='f')
345 _resp->lookups[n++] = *sp;
346 sp = NULL;
347 }
348 } else if (sp == NULL)
349 sp = cp;
350 }
351 continue;
352 }
353 /* set search list */
354 if (MATCH(buf, "search")) {
355 if (haveenv) /* skip if have from environ */
356 continue;
357 cp = buf + sizeof("search") - 1;
358 while (*cp == ' ' || *cp == '\t')
359 cp++;
360 if ((*cp == '\0') || (*cp == '\n'))
361 continue;
362 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
363 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
364 *cp = '\0';
365 /*
366 * Set search list to be blank-separated strings
367 * on rest of line.
368 */
369 cp = _resp->defdname;
370 pp = _resp->dnsrch;
371 *pp++ = cp;
372 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
373 if (*cp == ' ' || *cp == '\t') {
374 *cp = 0;
375 n = 1;
376 } else if (n) {
377 *pp++ = cp;
378 n = 0;
379 }
380 }
381 /* null terminate last domain if there are excess */
382 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
383 cp++;
384 *cp = '\0';
385 *pp++ = 0;
386 havesearch = 1;
387 continue;
388 }
389 /* read nameservers to query */
390 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
391#ifdef INET6
392 char *q;
393 struct addrinfo hints, *res;
394 char pbuf[NI_MAXSERV];
395#else
396 struct in_addr a;
397#endif /* INET6 */
398
399 cp = buf + sizeof("nameserver") - 1;
400 while (*cp == ' ' || *cp == '\t')
401 cp++;
402#ifdef INET6
403 if ((*cp == '\0') || (*cp == '\n'))
404 continue;
405 for (q = cp; *q; q++) {
406 if (isspace(*q)) {
407 *q = '\0';
408 break;
409 }
410 }
411 memset(&hints, 0, sizeof(hints));
412 hints.ai_flags = AI_NUMERICHOST;
413 hints.ai_socktype = SOCK_DGRAM;
414 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
415 res = NULL;
416 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
417 res->ai_next == NULL) {
418 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
419 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
420 res->ai_addrlen);
421 } else {
422 memset(&_res_extp->nsaddr_list[nserv], 0,
423 sizeof(_res_extp->nsaddr_list[nserv]));
424 }
425 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
426 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
427 res->ai_addrlen);
428 } else {
429 memset(&_resp->nsaddr_list[nserv], 0,
430 sizeof(_resp->nsaddr_list[nserv]));
431 }
432 nserv++;
433 }
434 if (res)
435 freeaddrinfo(res);
436#else /* INET6 */
437 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
438 _resp->nsaddr_list[nserv].sin_addr = a;
439 _resp->nsaddr_list[nserv].sin_family = AF_INET;
440 _resp->nsaddr_list[nserv].sin_port =
441 htons(NAMESERVER_PORT);
442 _resp->nsaddr_list[nserv].sin_len =
443 sizeof(struct sockaddr_in);
444 nserv++;
445 }
446#endif /* INET6 */
447 continue;
448 }
449#ifdef RESOLVSORT
450 if (MATCH(buf, "sortlist")) {
451 struct in_addr a;
452#ifdef INET6
453 struct in6_addr a6;
454 int m, i;
455 u_char *u;
456#endif /* INET6 */
457
458 cp = buf + sizeof("sortlist") - 1;
459 while (nsort < MAXRESOLVSORT) {
460 while (*cp == ' ' || *cp == '\t')
461 cp++;
462 if (*cp == '\0' || *cp == '\n' || *cp == ';')
463 break;
464 net = cp;
465 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
466 isascii(*cp) && !isspace(*cp))
467 cp++;
468 n = *cp;
469 *cp = 0;
470 if (inet_aton(net, &a)) {
471 _resp->sort_list[nsort].addr = a;
472 if (ISSORTMASK(n)) {
473 *cp++ = n;
474 net = cp;
475 while (*cp && *cp != ';' &&
476 isascii(*cp) && !isspace(*cp))
477 cp++;
478 n = *cp;
479 *cp = 0;
480 if (inet_aton(net, &a)) {
481 _resp->sort_list[nsort].mask = a.s_addr;
482 } else {
483 _resp->sort_list[nsort].mask =
484 net_mask(_resp->sort_list[nsort].addr);
485 }
486 } else {
487 _resp->sort_list[nsort].mask =
488 net_mask(_resp->sort_list[nsort].addr);
489 }
490#ifdef INET6
491 _res_extp->sort_list[nsort].af = AF_INET;
492 _res_extp->sort_list[nsort].addr.ina =
493 _resp->sort_list[nsort].addr;
494 _res_extp->sort_list[nsort].mask.ina.s_addr =
495 _resp->sort_list[nsort].mask;
496#endif /* INET6 */
497 nsort++;
498 }
499#ifdef INET6
500 else if (inet_pton(AF_INET6, net, &a6) == 1) {
501 _res_extp->sort_list[nsort].af = AF_INET6;
502 _res_extp->sort_list[nsort].addr.in6a = a6;
503 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
504 *cp++ = n;
505 net = cp;
506 while (*cp && *cp != ';' &&
507 isascii(*cp) && !isspace(*cp))
508 cp++;
509 m = n;
510 n = *cp;
511 *cp = 0;
512 switch (m) {
513 case '/':
514 m = atoi(net);
515 break;
516 case '&':
517 if (inet_pton(AF_INET6, net, u) == 1) {
518 m = -1;
519 break;
520 }
521 /*FALLTHRU*/
522 default:
523 m = sizeof(struct in6_addr) * NBBY;
524 break;
525 }
526 if (m >= 0) {
527 for (i = 0; i < sizeof(struct in6_addr); i++) {
528 if (m <= 0) {
529 *u = 0;
530 } else {
531 m -= NBBY;
532 *u = (u_char)~0;
533 if (m < 0)
534 *u <<= -m;
535 }
536 u++;
537 }
538 }
539 nsort++;
540 }
541#endif /* INET6 */
542 *cp = n;
543 }
544 continue;
545 }
546#endif
547 if (MATCH(buf, "options")) {
548 res_setoptions(buf + sizeof("options") - 1, "conf");
549 continue;
550 }
551 }
552 if (nserv > 1)
553 _resp->nscount = nserv;
554#ifdef RESOLVSORT
555 _resp->nsort = nsort;
556#endif
557 (void) fclose(fp);
558 }
559 if (_resp->defdname[0] == 0 &&
560 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
561 (cp = strchr(buf, '.')) != NULL)
562 {
563 strlcpy(_resp->defdname, cp + 1,
564 sizeof(_resp->defdname));
565 }
566
567 /* find components of local domain that might be searched */
568 if (havesearch == 0) {
569 pp = _resp->dnsrch;
570 *pp++ = _resp->defdname;
571 *pp = NULL;
572
573#ifndef RFC1535
574 dots = 0;
575 for (cp = _resp->defdname; *cp; cp++)
576 dots += (*cp == '.');
577
578 cp = _resp->defdname;
579 while (pp < _resp->dnsrch + MAXDFLSRCH) {
580 if (dots < LOCALDOMAINPARTS)
581 break;
582 cp = strchr(cp, '.') + 1; /* we know there is one */
583 *pp++ = cp;
584 dots--;
585 }
586 *pp = NULL;
587#ifdef DEBUG
588 if (_resp->options & RES_DEBUG) {
589 printf(";; res_init()... default dnsrch list:\n");
590 for (pp = _resp->dnsrch; *pp; pp++)
591 printf(";;\t%s\n", *pp);
592 printf(";;\t..END..\n");
593 }
594#endif /* DEBUG */
595#endif /* !RFC1535 */
596 }
597
598 if (issetugid())
599 _resp->options |= RES_NOALIASES;
600 else if ((cp = getenv("RES_OPTIONS")) != NULL)
601 res_setoptions(cp, "env");
602 _resp->options |= RES_INIT;
603 return (0);
604}
605
606/* ARGSUSED */
607static void
608res_setoptions(char *options, char *source)
609{
610 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
611 char *cp = options;
612 char *endp;
613 long l;
614
615#ifdef DEBUG
616 if (_resp->options & RES_DEBUG)
617 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
618 options, source);
619#endif
620 while (*cp) {
621 /* skip leading and inner runs of spaces */
622 while (*cp == ' ' || *cp == '\t')
623 cp++;
624 /* search for and process individual options */
625 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
626 char *p = cp + sizeof("ndots:") - 1;
627 l = strtol(p, &endp, 10);
628 if (l >= 0 && endp != p &&
629 (*endp = '\0' || isspace(*endp))) {
630 if (l <= RES_MAXNDOTS)
631 _resp->ndots = l;
632 else
633 _resp->ndots = RES_MAXNDOTS;
634#ifdef DEBUG
635 if (_resp->options & RES_DEBUG)
636 printf(";;\tndots=%u\n", _resp->ndots);
637#endif
638 }
639 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
640#ifdef DEBUG
641 if (!(_resp->options & RES_DEBUG)) {
642 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
643 options, source);
644 _resp->options |= RES_DEBUG;
645 }
646 printf(";;\tdebug\n");
647#endif
648 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
649 _resp->options |= RES_USE_INET6;
650 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
651 _resp->options |= RES_INSECURE1;
652 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
653 _resp->options |= RES_INSECURE2;
654 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
655 _resp->options |= RES_USE_EDNS0;
656 } else {
657 /* XXX - print a warning here? */
658 }
659 /* skip to next run of spaces */
660 while (*cp && *cp != ' ' && *cp != '\t')
661 cp++;
662 }
663}
664
665#ifdef RESOLVSORT
666/* XXX - should really support CIDR which means explicit masks always. */
667static u_int32_t
668net_mask(struct in_addr in) /* XXX - should really use system's version of this */
669{
670 u_int32_t i = ntohl(in.s_addr);
671
672 if (IN_CLASSA(i))
673 return (htonl(IN_CLASSA_NET));
674 else if (IN_CLASSB(i))
675 return (htonl(IN_CLASSB_NET));
676 return (htonl(IN_CLASSC_NET));
677}
678#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
new file mode 100644
index 0000000000..a6c37379f9
--- /dev/null
+++ b/src/lib/libc/net/res_mkquery.c
@@ -0,0 +1,241 @@
1/* $OpenBSD: res_mkquery.c,v 1.16 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1993
5 * -
6 * Copyright (c) 1985, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.16 2005/03/30 02:58:28 tedu Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/nameser.h>
67
68#include <stdio.h>
69#include <netdb.h>
70#include <resolv.h>
71#include <string.h>
72
73#include "thread_private.h"
74
75/*
76 * Form all types of queries.
77 * Returns the size of the result or -1.
78 */
79/* ARGSUSED */
80int
81res_mkquery(int op,
82 const char *dname, /* opcode of query */
83 int class, /* domain name */
84 int type, /* class and type of query */
85 const u_char *data, /* resource record data */
86 int datalen, /* length of data */
87 const u_char *newrr_in, /* new rr for modify or append */
88 u_char *buf, /* buffer to put query */
89 int buflen) /* size of buffer */
90{
91 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
92 HEADER *hp;
93 u_char *cp, *ep;
94 int n;
95 u_char *dnptrs[20], **dpp, **lastdnptr;
96
97 if (_res_init(0) == -1) {
98 h_errno = NETDB_INTERNAL;
99 return (-1);
100 }
101#ifdef DEBUG
102 if (_resp->options & RES_DEBUG)
103 printf(";; res_mkquery(%d, %s, %d, %d)\n",
104 op, dname, class, type);
105#endif
106 /*
107 * Initialize header fields.
108 *
109 * A special random number generator is used to create non predictable
110 * and non repeating ids over a long period. It also avoids reuse
111 * by switching between two distinct number cycles.
112 */
113
114 if ((buf == NULL) || (buflen < HFIXEDSZ))
115 return (-1);
116 bzero(buf, HFIXEDSZ);
117 hp = (HEADER *) buf;
118 _resp->id = res_randomid();
119 hp->id = htons(_resp->id);
120 hp->opcode = op;
121 hp->rd = (_resp->options & RES_RECURSE) != 0;
122 hp->rcode = NOERROR;
123 cp = buf + HFIXEDSZ;
124 ep = buf + buflen;
125 dpp = dnptrs;
126 *dpp++ = buf;
127 *dpp++ = NULL;
128 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
129 /*
130 * perform opcode specific processing
131 */
132 switch (op) {
133 case QUERY: /*FALLTHROUGH*/
134 case NS_NOTIFY_OP:
135 if (ep - cp < QFIXEDSZ)
136 return (-1);
137 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
138 lastdnptr)) < 0)
139 return (-1);
140 cp += n;
141 __putshort(type, cp);
142 cp += INT16SZ;
143 __putshort(class, cp);
144 cp += INT16SZ;
145 hp->qdcount = htons(1);
146 if (op == QUERY || data == NULL)
147 break;
148 /*
149 * Make an additional record for completion domain.
150 */
151 if (ep - cp < RRFIXEDSZ)
152 return (-1);
153 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
154 lastdnptr);
155 if (n < 0)
156 return (-1);
157 cp += n;
158 __putshort(T_NULL, cp);
159 cp += INT16SZ;
160 __putshort(class, cp);
161 cp += INT16SZ;
162 __putlong(0, cp);
163 cp += INT32SZ;
164 __putshort(0, cp);
165 cp += INT16SZ;
166 hp->arcount = htons(1);
167 break;
168
169 case IQUERY:
170 /*
171 * Initialize answer section
172 */
173 if (ep - cp < 1 + RRFIXEDSZ + datalen)
174 return (-1);
175 *cp++ = '\0'; /* no domain name */
176 __putshort(type, cp);
177 cp += INT16SZ;
178 __putshort(class, cp);
179 cp += INT16SZ;
180 __putlong(0, cp);
181 cp += INT32SZ;
182 __putshort(datalen, cp);
183 cp += INT16SZ;
184 if (datalen) {
185 bcopy(data, cp, datalen);
186 cp += datalen;
187 }
188 hp->ancount = htons(1);
189 break;
190
191 default:
192 return (-1);
193 }
194 return (cp - buf);
195}
196
197/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
198int
199res_opt(int n0,
200 u_char *buf, /* buffer to put query */
201 int buflen, /* size of buffer */
202 int anslen) /* answer buffer length */
203{
204 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
205 HEADER *hp;
206 u_char *cp, *ep;
207
208 hp = (HEADER *) buf;
209 cp = buf + n0;
210 ep = buf + buflen;
211
212 if (ep - cp < 1 + RRFIXEDSZ)
213 return -1;
214
215 *cp++ = 0; /* "." */
216
217 __putshort(T_OPT, cp); /* TYPE */
218 cp += INT16SZ;
219 if (anslen > 0xffff)
220 anslen = 0xffff; /* limit to 16bit value */
221 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
222 cp += INT16SZ;
223 *cp++ = NOERROR; /* extended RCODE */
224 *cp++ = 0; /* EDNS version */
225 if (_resp->options & RES_USE_DNSSEC) {
226#ifdef DEBUG
227 if (_resp->options & RES_DEBUG)
228 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
229#endif /* DEBUG */
230 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
231 cp += INT16SZ;
232 } else {
233 __putshort(0, cp); /* EDNS Z field */
234 cp += INT16SZ;
235 }
236 __putshort(0, cp); /* RDLEN */
237 cp += INT16SZ;
238 hp->arcount = htons(ntohs(hp->arcount) + 1);
239
240 return cp - buf;
241}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
new file mode 100644
index 0000000000..4af1651cf1
--- /dev/null
+++ b/src/lib/libc/net/res_query.c
@@ -0,0 +1,407 @@
1/* $OpenBSD: res_query.c,v 1.23 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * ++Copyright++ 1988, 1993
5 * -
6 * Copyright (c) 1988, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55#if 0
56static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_query.c,v 1.23 2005/03/30 02:58:28 tedu Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <arpa/nameser.h>
68
69#include <stdio.h>
70#include <netdb.h>
71#include <resolv.h>
72#include <ctype.h>
73#include <errno.h>
74#include <stdlib.h>
75#include <string.h>
76#include <unistd.h>
77
78#include "thread_private.h"
79
80#if PACKETSZ > 1024
81#define MAXPACKET PACKETSZ
82#else
83#define MAXPACKET 1024
84#endif
85
86const char *hostalias(const char *);
87int h_errno;
88extern int res_opt(int, u_char *, int, int);
89
90/*
91 * Formulate a normal query, send, and await answer.
92 * Returned answer is placed in supplied buffer "answer".
93 * Perform preliminary check of answer, returning success only
94 * if no error is indicated and the answer count is nonzero.
95 * Return the size of the response on success, -1 on error.
96 * Error number is left in h_errno.
97 *
98 * Caller must parse answer and determine whether it answers the question.
99 */
100int
101res_query(const char *name,
102 int class, /* domain name */
103 int type, /* class and type of query */
104 u_char *answer, /* buffer to put answer */
105 int anslen) /* size of answer buffer */
106{
107 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
108 u_char buf[MAXPACKET];
109 HEADER *hp = (HEADER *) answer;
110 int n;
111
112 hp->rcode = NOERROR; /* default */
113
114 if (_res_init(0) == -1) {
115 h_errno = NETDB_INTERNAL;
116 return (-1);
117 }
118#ifdef DEBUG
119 if (_resp->options & RES_DEBUG)
120 printf(";; res_query(%s, %d, %d)\n", name, class, type);
121#endif
122
123 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
124 buf, sizeof(buf));
125 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
126 (_resp->options & RES_USE_DNSSEC))) {
127 n = res_opt(n, buf, sizeof(buf), anslen);
128 }
129
130 if (n <= 0) {
131#ifdef DEBUG
132 if (_resp->options & RES_DEBUG)
133 printf(";; res_query: mkquery failed\n");
134#endif
135 h_errno = NO_RECOVERY;
136 return (n);
137 }
138 n = res_send(buf, n, answer, anslen);
139 if (n < 0) {
140#ifdef DEBUG
141 if (_resp->options & RES_DEBUG)
142 printf(";; res_query: send error\n");
143#endif
144 h_errno = TRY_AGAIN;
145 return (n);
146 }
147
148 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
149#ifdef DEBUG
150 if (_resp->options & RES_DEBUG)
151 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
152 ntohs(hp->ancount));
153#endif
154 switch (hp->rcode) {
155 case NXDOMAIN:
156 h_errno = HOST_NOT_FOUND;
157 break;
158 case SERVFAIL:
159 h_errno = TRY_AGAIN;
160 break;
161 case NOERROR:
162 h_errno = NO_DATA;
163 break;
164 case FORMERR:
165 case NOTIMP:
166 case REFUSED:
167 default:
168 h_errno = NO_RECOVERY;
169 break;
170 }
171 return (-1);
172 }
173 return (n);
174}
175
176/*
177 * Formulate a normal query, send, and retrieve answer in supplied buffer.
178 * Return the size of the response on success, -1 on error.
179 * If enabled, implement search rules until answer or unrecoverable failure
180 * is detected. Error code, if any, is left in h_errno.
181 */
182int
183res_search(const char *name,
184 int class, /* domain name */
185 int type, /* class and type of query */
186 u_char *answer, /* buffer to put answer */
187 int anslen) /* size of answer */
188{
189 const char *cp, * const *domain;
190 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
191 HEADER *hp = (HEADER *) answer;
192 u_int dots;
193 int trailing_dot, ret, saved_herrno;
194 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
195
196 if (_res_init(0) == -1) {
197 h_errno = NETDB_INTERNAL;
198 return (-1);
199 }
200 errno = 0;
201 h_errno = HOST_NOT_FOUND; /* default, if we never query */
202 dots = 0;
203 for (cp = name; *cp; cp++)
204 dots += (*cp == '.');
205 trailing_dot = 0;
206 if (cp > name && *--cp == '.')
207 trailing_dot++;
208
209 /*
210 * if there aren't any dots, it could be a user-level alias
211 */
212 if (!dots && (cp = __hostalias(name)) != NULL)
213 return (res_query(cp, class, type, answer, anslen));
214
215 /*
216 * If there are dots in the name already, let's just give it a try
217 * 'as is'. The threshold can be set with the "ndots" option.
218 */
219 saved_herrno = -1;
220 if (dots >= _resp->ndots) {
221 ret = res_querydomain(name, NULL, class, type, answer, anslen);
222 if (ret > 0)
223 return (ret);
224 saved_herrno = h_errno;
225 tried_as_is++;
226 }
227
228 /*
229 * We do at least one level of search if
230 * - there is no dot and RES_DEFNAME is set, or
231 * - there is at least one dot, there is no trailing dot,
232 * and RES_DNSRCH is set.
233 */
234 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
235 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
236 int done = 0;
237
238 for (domain = (const char * const *)_resp->dnsrch;
239 *domain && !done;
240 domain++) {
241
242 ret = res_querydomain(name, *domain, class, type,
243 answer, anslen);
244 if (ret > 0)
245 return (ret);
246
247 /*
248 * If no server present, give up.
249 * If name isn't found in this domain,
250 * keep trying higher domains in the search list
251 * (if that's enabled).
252 * On a NO_DATA error, keep trying, otherwise
253 * a wildcard entry of another type could keep us
254 * from finding this entry higher in the domain.
255 * If we get some other error (negative answer or
256 * server failure), then stop searching up,
257 * but try the input name below in case it's
258 * fully-qualified.
259 */
260 if (errno == ECONNREFUSED) {
261 h_errno = TRY_AGAIN;
262 return (-1);
263 }
264
265 switch (h_errno) {
266 case NO_DATA:
267 got_nodata++;
268 /* FALLTHROUGH */
269 case HOST_NOT_FOUND:
270 /* keep trying */
271 break;
272 case TRY_AGAIN:
273 if (hp->rcode == SERVFAIL) {
274 /* try next search element, if any */
275 got_servfail++;
276 break;
277 }
278 /* FALLTHROUGH */
279 default:
280 /* anything else implies that we're done */
281 done++;
282 }
283
284 /* if we got here for some reason other than DNSRCH,
285 * we only wanted one iteration of the loop, so stop.
286 */
287 if (!(_resp->options & RES_DNSRCH))
288 done++;
289 }
290 }
291
292 /* if we have not already tried the name "as is", do that now.
293 * note that we do this regardless of how many dots were in the
294 * name or whether it ends with a dot.
295 */
296 if (!tried_as_is) {
297 ret = res_querydomain(name, NULL, class, type, answer, anslen);
298 if (ret > 0)
299 return (ret);
300 }
301
302 /* if we got here, we didn't satisfy the search.
303 * if we did an initial full query, return that query's h_errno
304 * (note that we wouldn't be here if that query had succeeded).
305 * else if we ever got a nodata, send that back as the reason.
306 * else send back meaningless h_errno, that being the one from
307 * the last DNSRCH we did.
308 */
309 if (saved_herrno != -1)
310 h_errno = saved_herrno;
311 else if (got_nodata)
312 h_errno = NO_DATA;
313 else if (got_servfail)
314 h_errno = TRY_AGAIN;
315 return (-1);
316}
317
318/*
319 * Perform a call on res_query on the concatenation of name and domain,
320 * removing a trailing dot from name if domain is NULL.
321 */
322int
323res_querydomain(const char *name,
324 const char *domain,
325 int class, /* class and type of query */
326 int type,
327 u_char *answer, /* buffer to put answer */
328 int anslen) /* size of answer */
329{
330 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
331 char nbuf[MAXDNAME*2+1+1];
332 const char *longname = nbuf;
333 int n;
334
335 if (_res_init(0) == -1) {
336 h_errno = NETDB_INTERNAL;
337 return (-1);
338 }
339#ifdef DEBUG
340 if (_resp->options & RES_DEBUG)
341 printf(";; res_querydomain(%s, %s, %d, %d)\n",
342 name, domain?domain:"<Nil>", class, type);
343#endif
344 if (domain == NULL) {
345 /*
346 * Check for trailing '.';
347 * copy without '.' if present.
348 */
349 n = strlen(name) - 1;
350 if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
351 bcopy(name, nbuf, n);
352 nbuf[n] = '\0';
353 } else
354 longname = name;
355 } else
356 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
357 MAXDNAME, name, MAXDNAME, domain);
358
359 return (res_query(longname, class, type, answer, anslen));
360}
361
362const char *
363hostalias(const char *name)
364{
365 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
366 char *cp1, *cp2;
367 FILE *fp;
368 char *file;
369 char buf[BUFSIZ];
370 static char abuf[MAXDNAME];
371 size_t len;
372
373 if (_resp->options & RES_NOALIASES)
374 return (NULL);
375 file = getenv("HOSTALIASES");
376 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
377 return (NULL);
378 setbuf(fp, NULL);
379 while ((cp1 = fgetln(fp, &len)) != NULL) {
380 if (cp1[len-1] == '\n')
381 len--;
382 if (len >= sizeof(buf) || len == 0)
383 continue;
384 (void)memcpy(buf, cp1, len);
385 buf[len] = '\0';
386
387 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
388 ;
389 if (!*cp1)
390 break;
391 *cp1 = '\0';
392 if (!strcasecmp(buf, name)) {
393 while (isspace(*++cp1))
394 ;
395 if (!*cp1)
396 break;
397 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
398 ;
399 *cp2 = '\0';
400 strlcpy(abuf, cp1, sizeof(abuf));
401 fclose(fp);
402 return (abuf);
403 }
404 }
405 fclose(fp);
406 return (NULL);
407}
diff --git a/src/lib/libc/net/res_random.c b/src/lib/libc/net/res_random.c
new file mode 100644
index 0000000000..4dc1d33462
--- /dev/null
+++ b/src/lib/libc/net/res_random.c
@@ -0,0 +1,228 @@
1/* $OpenBSD: res_random.c,v 1.16 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
8 * such a mathematical system to generate more random (yet non-repeating)
9 * ids to solve the resolver/named problem. But Niels designed the
10 * actual system based on the constraints.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * seed = random 15bit
35 * n = prime, g0 = generator to n,
36 * j = random so that gcd(j,n-1) == 1
37 * g = g0^j mod n will be a generator again.
38 *
39 * X[0] = random seed.
40 * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
41 * with a = 7^(even random) mod m,
42 * b = random with gcd(b,m) == 1
43 * m = 31104 and a maximal period of m-1.
44 *
45 * The transaction id is determined by:
46 * id[n] = seed xor (g^X[n] mod n)
47 *
48 * Effectivly the id is restricted to the lower 15 bits, thus
49 * yielding two different cycles by toggling the msb on and off.
50 * This avoids reuse issues caused by reseeding.
51 *
52 * The 16 bit space is very small and brute force attempts are
53 * entirly feasible, we skip a random number of transaction ids
54 * so that an attacker will not get sequential ids.
55 */
56
57#include <sys/types.h>
58#include <netinet/in.h>
59#include <sys/time.h>
60#include <resolv.h>
61
62#include <unistd.h>
63#include <stdlib.h>
64#include <string.h>
65
66#define RU_OUT 180 /* Time after wich will be reseeded */
67#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
68#define RU_GEN 2 /* Starting generator */
69#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
70#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
71#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
72
73#define PFAC_N 3
74const static u_int16_t pfacts[PFAC_N] = {
75 2,
76 3,
77 2729
78};
79
80static u_int16_t ru_x;
81static u_int16_t ru_seed, ru_seed2;
82static u_int16_t ru_a, ru_b;
83static u_int16_t ru_g;
84static u_int16_t ru_counter = 0;
85static u_int16_t ru_msb = 0;
86static long ru_reseed;
87static u_int32_t tmp; /* Storage for unused random */
88static struct timeval tv;
89
90static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t);
91static void res_initid(void);
92
93/*
94 * Do a fast modular exponation, returned value will be in the range
95 * of 0 - (mod-1)
96 */
97
98static u_int16_t
99pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod)
100{
101 u_int16_t s, t, u;
102
103 s = 1;
104 t = gen;
105 u = exp;
106
107 while (u) {
108 if (u & 1)
109 s = (s * t) % mod;
110 u >>= 1;
111 t = (t * t) % mod;
112 }
113 return (s);
114}
115
116/*
117 * Initializes the seed and chooses a suitable generator. Also toggles
118 * the msb flag. The msb flag is used to generate two distinct
119 * cycles of random numbers and thus avoiding reuse of ids.
120 *
121 * This function is called from res_randomid() when needed, an
122 * application does not have to worry about it.
123 */
124static void
125res_initid(void)
126{
127 u_int16_t j, i;
128 int noprime = 1;
129
130 tmp = arc4random();
131 ru_x = (tmp & 0xFFFF) % RU_M;
132
133 /* 15 bits of random seed */
134 ru_seed = (tmp >> 16) & 0x7FFF;
135 tmp = arc4random();
136 ru_seed2 = tmp & 0x7FFF;
137
138 tmp = arc4random();
139
140 /* Determine the LCG we use */
141 ru_b = (tmp & 0xfffe) | 1;
142 ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
143 while (ru_b % 3 == 0)
144 ru_b += 2;
145
146 tmp = arc4random();
147 j = tmp % RU_N;
148 tmp = tmp >> 16;
149
150 /*
151 * Do a fast gcd(j,RU_N-1), so we can find a j with
152 * gcd(j, RU_N-1) == 1, giving a new generator for
153 * RU_GEN^j mod RU_N
154 */
155
156 while (noprime) {
157 for (i = 0; i < PFAC_N; i++)
158 if (j % pfacts[i] == 0)
159 break;
160
161 if (i >= PFAC_N)
162 noprime = 0;
163 else
164 j = (j + 1) % RU_N;
165 }
166
167 ru_g = pmod(RU_GEN, j, RU_N);
168 ru_counter = 0;
169
170 gettimeofday(&tv, NULL);
171 ru_reseed = tv.tv_sec + RU_OUT;
172 ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
173}
174
175u_int
176res_randomid(void)
177{
178 int i, n;
179
180 gettimeofday(&tv, NULL);
181 if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
182 res_initid();
183
184#if 0
185 if (!tmp)
186 tmp = arc4random();
187
188 /* Skip a random number of ids */
189 n = tmp & 0x7; tmp = tmp >> 3;
190 if (ru_counter + n >= RU_MAX)
191 res_initid();
192#else
193 n = 0;
194#endif
195
196 for (i = 0; i <= n; i++)
197 /* Linear Congruential Generator */
198 ru_x = (ru_a * ru_x + ru_b) % RU_M;
199
200 ru_counter += i;
201
202 return (ru_seed ^ pmod(ru_g, ru_seed2 + ru_x, RU_N)) | ru_msb;
203}
204
205#if 0
206void
207main(int argc, char **argv)
208{
209 int i, n;
210 u_int16_t wert;
211
212 res_initid();
213
214 printf("Generator: %u\n", ru_g);
215 printf("Seed: %u\n", ru_seed);
216 printf("Reseed at %ld\n", ru_reseed);
217 printf("Ru_X: %u\n", ru_x);
218 printf("Ru_A: %u\n", ru_a);
219 printf("Ru_B: %u\n", ru_b);
220
221 n = atoi(argv[1]);
222 for (i=0;i<n;i++) {
223 wert = res_randomid();
224 printf("%06d\n", wert);
225 }
226}
227#endif
228
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
new file mode 100644
index 0000000000..ee7ce43035
--- /dev/null
+++ b/src/lib/libc/net/res_send.c
@@ -0,0 +1,879 @@
1/* $OpenBSD: res_send.c,v 1.18 2005/03/30 02:58:28 tedu Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 1993
7 * The Regents of the University of California. All rights reserved.
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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#ifndef INET6
55#define INET6
56#endif
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_send.c,v 1.18 2005/03/30 02:58:28 tedu Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67 /* change this to "0"
68 * if you talk to a lot
69 * of multi-homed SunOS
70 * ("broken") name servers.
71 */
72#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
73
74/*
75 * Send query to name server and wait for reply.
76 */
77
78#include <sys/types.h>
79#include <sys/param.h>
80#include <sys/time.h>
81#include <sys/socket.h>
82#include <sys/uio.h>
83#include <netinet/in.h>
84#include <arpa/nameser.h>
85#include <arpa/inet.h>
86
87#include <stdio.h>
88#include <netdb.h>
89#include <errno.h>
90#include <resolv.h>
91#include <stdlib.h>
92#include <string.h>
93#include <unistd.h>
94
95#include "thread_private.h"
96
97static int s = -1; /* socket used for communications */
98static int connected = 0; /* is the socket connected */
99static int vc = 0; /* is the socket a virtual ciruit? */
100static int af = 0; /* address family of socket */
101
102#ifndef FD_SET
103/* XXX - should be in portability.h */
104#define NFDBITS 32
105#define FD_SETSIZE 32
106#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
107#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
108#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
109#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
110#endif
111
112#define CAN_RECONNECT 1
113
114#ifndef DEBUG
115# define Dprint(cond, args) /*empty*/
116# define DprintQ(cond, args, query, size) /*empty*/
117# define Aerror(file, string, error, address) /*empty*/
118# define Perror(file, string, error) /*empty*/
119#else
120# define Dprint(cond, args) if (cond) {fprintf args;} else {}
121# define DprintQ(cond, args, query, size) if (cond) {\
122 fprintf args;\
123 __fp_nquery(query, size, stdout);\
124 } else {}
125static char abuf[NI_MAXHOST];
126static char pbuf[NI_MAXSERV];
127static void Aerror(FILE *, char *, int, struct sockaddr *);
128static void Perror(FILE *, char *, int);
129
130 static void
131 Aerror(FILE *file, char *string, int error, struct sockaddr *address)
132 {
133 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
134 int save = errno;
135
136 if (_resp->options & RES_DEBUG) {
137 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
138 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
139 strlcpy(abuf, "?", sizeof(abuf));
140 strlcpy(pbuf, "?", sizeof(pbuf));
141 }
142 fprintf(file, "res_send: %s ([%s].%s): %s\n",
143 string, abuf, pbuf, strerror(error));
144 }
145 errno = save;
146 }
147 static void
148 Perror(FILE *file, char *string, int error)
149 {
150 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
151 int save = errno;
152
153 if (_resp->options & RES_DEBUG) {
154 fprintf(file, "res_send: %s: %s\n",
155 string, strerror(error));
156 }
157 errno = save;
158 }
159#endif
160
161static res_send_qhook Qhook = NULL;
162static res_send_rhook Rhook = NULL;
163
164void
165res_send_setqhook(res_send_qhook hook)
166{
167
168 Qhook = hook;
169}
170
171void
172res_send_setrhook(res_send_rhook hook)
173{
174
175 Rhook = hook;
176}
177
178#ifdef INET6
179static struct sockaddr * get_nsaddr(size_t);
180
181/*
182 * pick appropriate nsaddr_list for use. see res_init() for initialization.
183 */
184static struct sockaddr *
185get_nsaddr(size_t n)
186{
187 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
188 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
189 &_res_ext);
190
191 if (!_resp->nsaddr_list[n].sin_family) {
192 /*
193 * - _res_extp->nsaddr_list[n] holds an address that is larger
194 * than struct sockaddr, and
195 * - user code did not update _resp->nsaddr_list[n].
196 */
197 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
198 } else {
199 /*
200 * - user code updated _res.nsaddr_list[n], or
201 * - _resp->nsaddr_list[n] has the same content as
202 * _res_extp->nsaddr_list[n].
203 */
204 return (struct sockaddr *)&_resp->nsaddr_list[n];
205 }
206}
207#else
208#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
209#endif
210
211/* int
212 * res_isourserver(ina)
213 * looks up "ina" in _resp->ns_addr_list[]
214 * returns:
215 * 0 : not found
216 * >0 : found
217 * author:
218 * paul vixie, 29may94
219 */
220int
221res_isourserver(const struct sockaddr_in *inp)
222{
223 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
224#ifdef INET6
225 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
226 const struct sockaddr_in6 *srv6;
227#endif
228 const struct sockaddr_in *srv;
229 int ns, ret;
230
231 ret = 0;
232 switch (inp->sin_family) {
233#ifdef INET6
234 case AF_INET6:
235 for (ns = 0; ns < _resp->nscount; ns++) {
236 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
237 if (srv6->sin6_family == in6p->sin6_family &&
238 srv6->sin6_port == in6p->sin6_port &&
239 srv6->sin6_scope_id == in6p->sin6_scope_id &&
240 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
241 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
242 &in6p->sin6_addr))) {
243 ret++;
244 break;
245 }
246 }
247 break;
248#endif
249 case AF_INET:
250 for (ns = 0; ns < _resp->nscount; ns++) {
251 srv = (struct sockaddr_in *)get_nsaddr(ns);
252 if (srv->sin_family == inp->sin_family &&
253 srv->sin_port == inp->sin_port &&
254 (srv->sin_addr.s_addr == INADDR_ANY ||
255 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
256 ret++;
257 break;
258 }
259 }
260 break;
261 }
262 return (ret);
263}
264
265/* int
266 * res_nameinquery(name, type, class, buf, eom)
267 * look for (name,type,class) in the query section of packet (buf,eom)
268 * returns:
269 * -1 : format error
270 * 0 : not found
271 * >0 : found
272 * author:
273 * paul vixie, 29may94
274 */
275int
276res_nameinquery(const char *name, int type, int class, const u_char *buf,
277 const u_char *eom)
278{
279 const u_char *cp = buf + HFIXEDSZ;
280 int qdcount = ntohs(((HEADER*)buf)->qdcount);
281
282 while (qdcount-- > 0) {
283 char tname[MAXDNAME+1];
284 int n, ttype, tclass;
285
286 n = dn_expand(buf, eom, cp, tname, sizeof tname);
287 if (n < 0)
288 return (-1);
289 cp += n;
290 ttype = _getshort(cp); cp += INT16SZ;
291 tclass = _getshort(cp); cp += INT16SZ;
292 if (ttype == type &&
293 tclass == class &&
294 strcasecmp(tname, name) == 0)
295 return (1);
296 }
297 return (0);
298}
299
300/* int
301 * res_queriesmatch(buf1, eom1, buf2, eom2)
302 * is there a 1:1 mapping of (name,type,class)
303 * in (buf1,eom1) and (buf2,eom2)?
304 * returns:
305 * -1 : format error
306 * 0 : not a 1:1 mapping
307 * >0 : is a 1:1 mapping
308 * author:
309 * paul vixie, 29may94
310 */
311int
312res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2,
313 const u_char *eom2)
314{
315 const u_char *cp = buf1 + HFIXEDSZ;
316 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
317
318 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
319 return (0);
320 while (qdcount-- > 0) {
321 char tname[MAXDNAME+1];
322 int n, ttype, tclass;
323
324 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
325 if (n < 0)
326 return (-1);
327 cp += n;
328 ttype = _getshort(cp); cp += INT16SZ;
329 tclass = _getshort(cp); cp += INT16SZ;
330 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
331 return (0);
332 }
333 return (1);
334}
335
336int
337res_send(const u_char *buf, int buflen, u_char *ans, int anssiz)
338{
339 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
340 HEADER *hp = (HEADER *) buf;
341 HEADER *anhp = (HEADER *) ans;
342 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
343 int n;
344 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
345
346 if (_res_init(0) == -1) {
347 /* errno should have been set by res_init() in this case. */
348 return (-1);
349 }
350 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
351 (stdout, ";; res_send()\n"), buf, buflen);
352 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
353 gotsomewhere = 0;
354 connreset = 0;
355 terrno = ETIMEDOUT;
356 badns = 0;
357
358 /*
359 * Send request, RETRY times, or until successful
360 */
361 for (try = 0; try < _resp->retry; try++) {
362 for (ns = 0; ns < _resp->nscount; ns++) {
363 struct sockaddr *nsap = get_nsaddr(ns);
364 socklen_t salen;
365
366 if (nsap->sa_len)
367 salen = nsap->sa_len;
368#ifdef INET6
369 else if (nsap->sa_family == AF_INET6)
370 salen = sizeof(struct sockaddr_in6);
371#endif
372 else if (nsap->sa_family == AF_INET)
373 salen = sizeof(struct sockaddr_in);
374 else
375 salen = 0; /*unknown, die on connect*/
376
377 same_ns:
378 if (badns & (1 << ns)) {
379 res_close();
380 goto next_ns;
381 }
382
383 if (Qhook) {
384 int done = 0, loops = 0;
385
386 do {
387 res_sendhookact act;
388
389 act = (*Qhook)((struct sockaddr_in **)&nsap,
390 &buf, &buflen,
391 ans, anssiz, &resplen);
392 switch (act) {
393 case res_goahead:
394 done = 1;
395 break;
396 case res_nextns:
397 res_close();
398 goto next_ns;
399 case res_done:
400 return (resplen);
401 case res_modified:
402 /* give the hook another try */
403 if (++loops < 42) /*doug adams*/
404 break;
405 /*FALLTHROUGH*/
406 case res_error:
407 /*FALLTHROUGH*/
408 default:
409 return (-1);
410 }
411 } while (!done);
412 }
413
414 Dprint((_resp->options & RES_DEBUG) &&
415 getnameinfo(nsap, salen, abuf, sizeof(abuf),
416 NULL, 0, NI_NUMERICHOST) == 0,
417 (stdout, ";; Querying server (# %d) address = %s\n",
418 ns + 1, abuf));
419
420 if (v_circuit) {
421 int truncated;
422 struct iovec iov[2];
423 u_short len;
424 u_char *cp;
425
426 /*
427 * Use virtual circuit;
428 * at most one attempt per server.
429 */
430 try = _resp->retry;
431 truncated = 0;
432 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
433 if (s >= 0)
434 res_close();
435
436 af = nsap->sa_family;
437 s = socket(af, SOCK_STREAM, 0);
438 if (s < 0) {
439 terrno = errno;
440 Perror(stderr, "socket(vc)", errno);
441#if 0
442 return (-1);
443#else
444 badns |= (1 << ns);
445 res_close();
446 goto next_ns;
447#endif
448 }
449 errno = 0;
450 if (connect(s, nsap, salen) < 0) {
451 terrno = errno;
452 Aerror(stderr, "connect/vc",
453 errno, nsap);
454 badns |= (1 << ns);
455 res_close();
456 goto next_ns;
457 }
458 vc = 1;
459 }
460 /*
461 * Send length & message
462 */
463 putshort((u_short)buflen, (u_char*)&len);
464 iov[0].iov_base = (caddr_t)&len;
465 iov[0].iov_len = INT16SZ;
466 iov[1].iov_base = (caddr_t)buf;
467 iov[1].iov_len = buflen;
468 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
469 terrno = errno;
470 Perror(stderr, "write failed", errno);
471 badns |= (1 << ns);
472 res_close();
473 goto next_ns;
474 }
475 /*
476 * Receive length & response
477 */
478read_len:
479 cp = ans;
480 len = INT16SZ;
481 while ((n = read(s, (char *)cp, (int)len)) > 0) {
482 cp += n;
483 if ((len -= n) <= 0)
484 break;
485 }
486 if (n <= 0) {
487 terrno = errno;
488 Perror(stderr, "read failed", errno);
489 res_close();
490 /*
491 * A long running process might get its TCP
492 * connection reset if the remote server was
493 * restarted. Requery the server instead of
494 * trying a new one. When there is only one
495 * server, this means that a query might work
496 * instead of failing. We only allow one reset
497 * per query to prevent looping.
498 */
499 if (terrno == ECONNRESET && !connreset) {
500 connreset = 1;
501 res_close();
502 goto same_ns;
503 }
504 res_close();
505 goto next_ns;
506 }
507 resplen = _getshort(ans);
508 if (resplen > anssiz) {
509 Dprint(_resp->options & RES_DEBUG,
510 (stdout, ";; response truncated\n")
511 );
512 truncated = 1;
513 len = anssiz;
514 } else
515 len = resplen;
516 cp = ans;
517 while (len != 0 &&
518 (n = read(s, (char *)cp, (int)len)) > 0) {
519 cp += n;
520 len -= n;
521 }
522 if (n <= 0) {
523 terrno = errno;
524 Perror(stderr, "read(vc)", errno);
525 res_close();
526 goto next_ns;
527 }
528 if (truncated) {
529 /*
530 * Flush rest of answer
531 * so connection stays in synch.
532 */
533 anhp->tc = 1;
534 len = resplen - anssiz;
535 while (len != 0) {
536 char junk[PACKETSZ];
537
538 n = (len > sizeof(junk)
539 ? sizeof(junk)
540 : len);
541 if ((n = read(s, junk, n)) > 0)
542 len -= n;
543 else
544 break;
545 }
546 }
547 /*
548 * The calling applicating has bailed out of
549 * a previous call and failed to arrange to have
550 * the circuit closed or the server has got
551 * itself confused. Anyway drop the packet and
552 * wait for the correct one.
553 */
554 if (hp->id != anhp->id) {
555 DprintQ((_resp->options & RES_DEBUG) ||
556 (_resp->pfcode & RES_PRF_REPLY),
557 (stdout, ";; old answer (unexpected):\n"),
558 ans, (resplen>anssiz)?anssiz:resplen);
559 goto read_len;
560 }
561 } else {
562 /*
563 * Use datagrams.
564 */
565 struct timeval timeout;
566 fd_set *dsmaskp;
567 struct sockaddr_storage from;
568 socklen_t fromlen;
569
570 if ((s < 0) || vc || (af != nsap->sa_family)) {
571 if (vc)
572 res_close();
573 af = nsap->sa_family;
574 s = socket(af, SOCK_DGRAM, 0);
575 if (s < 0) {
576#if !CAN_RECONNECT
577 bad_dg_sock:
578#endif
579 terrno = errno;
580 Perror(stderr, "socket(dg)", errno);
581#if 0
582 return (-1);
583#else
584 badns |= (1 << ns);
585 res_close();
586 goto next_ns;
587#endif
588 }
589#ifdef IPV6_MINMTU
590 if (af == AF_INET6) {
591 const int yes = 1;
592 (void)setsockopt(s, IPPROTO_IPV6,
593 IPV6_USE_MIN_MTU, &yes,
594 sizeof(yes));
595 }
596#endif
597 connected = 0;
598 }
599 /*
600 * On a 4.3BSD+ machine (client and server,
601 * actually), sending to a nameserver datagram
602 * port with no nameserver will cause an
603 * ICMP port unreachable message to be returned.
604 * If our datagram socket is "connected" to the
605 * server, we get an ECONNREFUSED error on the next
606 * socket operation, and select returns if the
607 * error message is received. We can thus detect
608 * the absence of a nameserver without timing out.
609 * If we have sent queries to at least two servers,
610 * however, we don't want to remain connected,
611 * as we wish to receive answers from the first
612 * server to respond.
613 */
614 if (!(_resp->options & RES_INSECURE1) &&
615 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
616 /*
617 * Connect only if we are sure we won't
618 * receive a response from another server.
619 */
620 if (!connected) {
621 if (connect(s, nsap, salen) < 0) {
622 Aerror(stderr,
623 "connect(dg)",
624 errno, nsap);
625 badns |= (1 << ns);
626 res_close();
627 goto next_ns;
628 }
629 connected = 1;
630 }
631 if (send(s, (char*)buf, buflen, 0) != buflen) {
632 Perror(stderr, "send", errno);
633 badns |= (1 << ns);
634 res_close();
635 goto next_ns;
636 }
637 } else {
638 /*
639 * Disconnect if we want to listen
640 * for responses from more than one server.
641 */
642 if (connected) {
643#if CAN_RECONNECT
644#ifdef INET6
645 /* XXX: any errornous address */
646#endif /* INET6 */
647 struct sockaddr_in no_addr;
648
649 no_addr.sin_family = AF_INET;
650 no_addr.sin_addr.s_addr = INADDR_ANY;
651 no_addr.sin_port = 0;
652 (void) connect(s,
653 (struct sockaddr *)
654 &no_addr,
655 sizeof(no_addr));
656#else
657 int s1 = socket(af, SOCK_DGRAM,0);
658 if (s1 < 0)
659 goto bad_dg_sock;
660 (void) dup2(s1, s);
661 (void) close(s1);
662 Dprint(_resp->options & RES_DEBUG,
663 (stdout, ";; new DG socket\n"))
664#endif
665#ifdef IPV6_MINMTU
666 if (af == AF_INET6) {
667 const int yes = 1;
668 (void)setsockopt(s, IPPROTO_IPV6,
669 IPV6_USE_MIN_MTU, &yes,
670 sizeof(yes));
671 }
672#endif
673 connected = 0;
674 errno = 0;
675 }
676 if (sendto(s, (char*)buf, buflen, 0,
677 nsap, salen) != buflen) {
678 Aerror(stderr, "sendto", errno, nsap);
679 badns |= (1 << ns);
680 res_close();
681 goto next_ns;
682 }
683 }
684
685 /*
686 * Wait for reply
687 */
688 timeout.tv_sec = (_resp->retrans << try);
689 if (try > 0)
690 timeout.tv_sec /= _resp->nscount;
691 if ((long) timeout.tv_sec <= 0)
692 timeout.tv_sec = 1;
693 timeout.tv_usec = 0;
694 wait:
695 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
696 sizeof(fd_mask));
697 if (dsmaskp == NULL) {
698 res_close();
699 goto next_ns;
700 }
701 FD_SET(s, dsmaskp);
702 n = select(s+1, dsmaskp, (fd_set *)NULL,
703 (fd_set *)NULL, &timeout);
704 free(dsmaskp);
705 if (n < 0) {
706 if (errno == EINTR)
707 goto wait;
708 Perror(stderr, "select", errno);
709 res_close();
710 goto next_ns;
711 }
712 if (n == 0) {
713 /*
714 * timeout
715 */
716 Dprint(_resp->options & RES_DEBUG,
717 (stdout, ";; timeout\n"));
718 gotsomewhere = 1;
719 res_close();
720 goto next_ns;
721 }
722 errno = 0;
723 fromlen = sizeof(from);
724 resplen = recvfrom(s, (char*)ans, anssiz, 0,
725 (struct sockaddr *)&from, &fromlen);
726 if (resplen <= 0) {
727 Perror(stderr, "recvfrom", errno);
728 res_close();
729 goto next_ns;
730 }
731 gotsomewhere = 1;
732 if (hp->id != anhp->id) {
733 /*
734 * response from old query, ignore it.
735 * XXX - potential security hazard could
736 * be detected here.
737 */
738 DprintQ((_resp->options & RES_DEBUG) ||
739 (_resp->pfcode & RES_PRF_REPLY),
740 (stdout, ";; old answer:\n"),
741 ans, (resplen>anssiz)?anssiz:resplen);
742 goto wait;
743 }
744#if CHECK_SRVR_ADDR
745 if (!(_resp->options & RES_INSECURE1) &&
746 !res_isourserver((struct sockaddr_in *)&from)) {
747 /*
748 * response from wrong server? ignore it.
749 * XXX - potential security hazard could
750 * be detected here.
751 */
752 DprintQ((_resp->options & RES_DEBUG) ||
753 (_resp->pfcode & RES_PRF_REPLY),
754 (stdout, ";; not our server:\n"),
755 ans, (resplen>anssiz)?anssiz:resplen);
756 goto wait;
757 }
758#endif
759 if (!(_resp->options & RES_INSECURE2) &&
760 !res_queriesmatch(buf, buf + buflen,
761 ans, ans + anssiz)) {
762 /*
763 * response contains wrong query? ignore it.
764 * XXX - potential security hazard could
765 * be detected here.
766 */
767 DprintQ((_resp->options & RES_DEBUG) ||
768 (_resp->pfcode & RES_PRF_REPLY),
769 (stdout, ";; wrong query name:\n"),
770 ans, (resplen>anssiz)?anssiz:resplen);
771 goto wait;
772 }
773 if (anhp->rcode == SERVFAIL ||
774 anhp->rcode == NOTIMP ||
775 anhp->rcode == REFUSED) {
776 DprintQ(_resp->options & RES_DEBUG,
777 (stdout, "server rejected query:\n"),
778 ans, (resplen>anssiz)?anssiz:resplen);
779 badns |= (1 << ns);
780 res_close();
781 /* don't retry if called from dig */
782 if (!_resp->pfcode)
783 goto next_ns;
784 }
785 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
786 /*
787 * get rest of answer;
788 * use TCP with same server.
789 */
790 Dprint(_resp->options & RES_DEBUG,
791 (stdout, ";; truncated answer\n"));
792 v_circuit = 1;
793 res_close();
794 goto same_ns;
795 }
796 } /*if vc/dg*/
797 Dprint((_resp->options & RES_DEBUG) ||
798 ((_resp->pfcode & RES_PRF_REPLY) &&
799 (_resp->pfcode & RES_PRF_HEAD1)),
800 (stdout, ";; got answer:\n"));
801 DprintQ((_resp->options & RES_DEBUG) ||
802 (_resp->pfcode & RES_PRF_REPLY),
803 (stdout, "%s", ""),
804 ans, (resplen>anssiz)?anssiz:resplen);
805 /*
806 * If using virtual circuits, we assume that the first server
807 * is preferred over the rest (i.e. it is on the local
808 * machine) and only keep that one open.
809 * If we have temporarily opened a virtual circuit,
810 * or if we haven't been asked to keep a socket open,
811 * close the socket.
812 */
813 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
814 !(_resp->options & RES_STAYOPEN)) {
815 res_close();
816 }
817 if (Rhook) {
818 int done = 0, loops = 0;
819
820 do {
821 res_sendhookact act;
822
823 act = (*Rhook)((struct sockaddr_in *)nsap,
824 buf, buflen,
825 ans, anssiz, &resplen);
826 switch (act) {
827 case res_goahead:
828 case res_done:
829 done = 1;
830 break;
831 case res_nextns:
832 res_close();
833 goto next_ns;
834 case res_modified:
835 /* give the hook another try */
836 if (++loops < 42) /*doug adams*/
837 break;
838 /*FALLTHROUGH*/
839 case res_error:
840 /*FALLTHROUGH*/
841 default:
842 return (-1);
843 }
844 } while (!done);
845
846 }
847 return (resplen);
848 next_ns: ;
849 } /*foreach ns*/
850 } /*foreach retry*/
851 res_close();
852 if (!v_circuit) {
853 if (!gotsomewhere)
854 errno = ECONNREFUSED; /* no nameservers found */
855 else
856 errno = ETIMEDOUT; /* no answer obtained */
857 } else
858 errno = terrno;
859 return (-1);
860}
861
862/*
863 * This routine is for closing the socket if a virtual circuit is used and
864 * the program wants to close it. This provides support for endhostent()
865 * which expects to close the socket.
866 *
867 * This routine is not expected to be user visible.
868 */
869void
870res_close(void)
871{
872 if (s >= 0) {
873 (void) close(s);
874 s = -1;
875 connected = 0;
876 vc = 0;
877 af = 0;
878 }
879}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
new file mode 100644
index 0000000000..d1eb2298ae
--- /dev/null
+++ b/src/lib/libc/net/resolver.3
@@ -0,0 +1,354 @@
1.\" $OpenBSD: resolver.3,v 1.19 2005/04/05 22:14:20 fgsch Exp $
2.\"
3.\" Copyright (c) 1985, 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 June 4, 1993
31.Dt RESOLVER 3
32.Os
33.Sh NAME
34.Nm res_query ,
35.Nm res_search ,
36.Nm res_mkquery ,
37.Nm res_send ,
38.Nm res_init ,
39.Nm dn_comp ,
40.Nm dn_expand
41.Nd resolver routines
42.Sh SYNOPSIS
43.Fd #include <sys/types.h>
44.Fd #include <netinet/in.h>
45.Fd #include <arpa/nameser.h>
46.Fd #include <resolv.h>
47.Ft int
48.Fo res_query
49.Fa "const char *dname"
50.Fa "int class"
51.Fa "int type"
52.Fa "u_char *answer"
53.Fa "int anslen"
54.Fc
55.Ft int
56.Fo res_search
57.Fa "const char *dname"
58.Fa "int class"
59.Fa "int type"
60.Fa "u_char *answer"
61.Fa "int anslen"
62.Fc
63.Ft int
64.Fo res_mkquery
65.Fa "int op"
66.Fa "const char *dname"
67.Fa "int class"
68.Fa "int type"
69.Fa "const u_char *data"
70.Fa "int datalen"
71.Fa "const u_char *newrr"
72.Fa "u_char *buf"
73.Fa "int buflen"
74.Fc
75.Ft int
76.Fo res_send
77.Fa "const u_char *msg"
78.Fa "int msglen"
79.Fa "u_char *answer"
80.Fa "int anslen"
81.Fc
82.Ft int
83.Fn res_init "void"
84.Ft int
85.Fo dn_comp
86.Fa "const char *exp_dn"
87.Fa "u_char *comp_dn"
88.Fa "int length"
89.Fa "u_char **dnptrs"
90.Fa "u_char **lastdnptr"
91.Fc
92.Ft int
93.Fo dn_expand
94.Fa "const u_char *msg"
95.Fa "const u_char *eomorig"
96.Fa "const u_char *comp_dn"
97.Fa "char *exp_dn"
98.Fa "int length"
99.Fc
100.Sh DESCRIPTION
101These routines are used for making, sending, and interpreting
102query and reply messages with Internet domain name servers.
103.Pp
104Global configuration and state information that is used by the
105resolver routines is kept in the structure
106.Li _res .
107Most of the values have reasonable defaults and can be ignored.
108Options stored in
109.Li _res.options
110are defined in
111.Aq Pa resolv.h
112and are as follows.
113Options are stored as a simple bit mask containing the bitwise
114.Tn OR
115of the options enabled.
116.Bl -tag -width RES_USE_INET6
117.It Dv RES_INIT
118True if the initial name server address and default domain name are
119initialized (i.e.,
120.Fn res_init
121has been called).
122.It Dv RES_DEBUG
123Print debugging messages.
124.It Dv RES_AAONLY
125Accept authoritative answers only.
126With this option,
127.Fn res_send
128should continue until it finds an authoritative answer or finds an error.
129Currently this is not implemented.
130.It Dv RES_USEVC
131Use
132.Tn TCP
133connections for queries instead of
134.Tn UDP
135datagrams.
136.It Dv RES_STAYOPEN
137Used with
138.Dv RES_USEVC
139to keep the
140.Tn TCP
141connection open between queries.
142This is useful only in programs that regularly do many queries.
143.Tn UDP
144should be the normal mode used.
145.It Dv RES_IGNTC
146Unused currently (ignore truncation errors, i.e., don't retry with
147.Tn TCP ) .
148.It Dv RES_RECURSE
149Set the recursion-desired bit in queries.
150This is the default.
151.Pf ( Fn res_send
152does not do iterative queries and expects the name server
153to handle recursion.)
154.It Dv RES_DEFNAMES
155If set,
156.Fn res_search
157will append the default domain name to single-component names
158(those that do not contain a dot).
159This option is enabled by default.
160.It Dv RES_DNSRCH
161If this option is set,
162.Fn res_search
163will search for host names in the current domain and in parent domains; see
164.Xr hostname 7 .
165This is used by the standard host lookup routine
166.Xr gethostbyname 3 .
167This option is enabled by default.
168.It Dv RES_USE_INET6
169Enables support for IPv6-only applications.
170This causes IPv4 addresses to be returned as an IPv4 mapped address.
171For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
172The option is not meaningful on
173.Ox .
174.It Dv RES_USE_EDNS0
175Enables support for OPT pseudo-RR for EDNS0 extension.
176With this option, resolver code will attach OPT pseudo-RR into DNS queries,
177to inform of our receive buffer size.
178The option will allow DNS servers to take advantage of non-default receive
179buffer size, and to send larger replies.
180DNS query packets with EDNS0 extension is not compatible with
181non-EDNS0 DNS servers.
182.El
183.Pp
184The
185.Fn res_init
186routine reads the configuration file (if any; see
187.Xr resolv.conf 5 )
188to get the default domain name, search list, and the Internet address
189of the local name server(s).
190If no server is configured, the host running
191the resolver is tried.
192The current domain name is defined by the hostname
193if not specified in the configuration file;
194it can be overridden by the environment variable
195.Ev LOCALDOMAIN .
196This environment variable may contain several blank-separated
197tokens if you wish to override the
198.Fa search list
199on a per-process basis.
200This is similar to the
201.Fa search
202command in the configuration file.
203Another environment variable
204.Ev RES_OPTIONS
205can be set to override certain internal resolver options which
206are otherwise set by changing fields in the
207.Fa _res
208structure or are inherited from the configuration file's
209.Fa options
210command.
211The syntax of the
212.Ev RES_OPTIONS
213environment variable is explained in
214.Xr resolv.conf 5 .
215Initialization normally occurs on the first call
216to one of the following routines.
217.Pp
218The
219.Fn res_query
220function provides an interface to the server query mechanism.
221It constructs a query, sends it to the local server,
222awaits a response, and makes preliminary checks on the reply.
223The query requests information of the specified
224.Fa type
225and
226.Fa class
227for the specified fully qualified domain name
228.Fa dname .
229The reply message is left in the
230.Fa answer
231buffer with length
232.Fa anslen
233supplied by the caller.
234Values for the
235.Fa class
236and
237.Fa type
238fields
239are defined in
240.Aq Pa arpa/nameserv.h .
241.Pp
242The
243.Fn res_search
244routine makes a query and awaits a response like
245.Fn res_query ,
246but in addition, it implements the default and search rules controlled by the
247.Dv RES_DEFNAMES
248and
249.Dv RES_DNSRCH
250options.
251It returns the first successful reply.
252.Pp
253The remaining routines are lower-level routines used by
254.Fn res_query .
255The
256.Fn res_mkquery
257function constructs a standard query message and places it in
258.Fa buf .
259It returns the size of the query, or \-1 if the query is larger than
260.Fa buflen .
261The query type
262.Fa op
263is usually
264.Dv QUERY ,
265but can be any of the query types defined in
266.Aq Pa arpa/nameser.h .
267The domain name for the query is given by
268.Fa dname .
269.Fa newrr
270is currently unused but is intended for making update messages.
271.Pp
272The
273.Fn res_send
274routine sends a pre-formatted query and returns an answer.
275It will call
276.Fn res_init
277if
278.Dv RES_INIT
279is not set, send the query to the local name server, and
280handle timeouts and retries.
281The length of the reply message is returned, or \-1 if there were errors.
282.Pp
283The
284.Fn dn_comp
285function compresses the domain name
286.Fa exp_dn
287and stores it in
288.Fa comp_dn .
289The size of the compressed name is returned or \-1 if there were errors.
290The size of the array pointed to by
291.Fa comp_dn
292is given by
293.Fa length .
294The compression uses an array of pointers
295.Fa dnptrs
296to previously compressed names in the current message.
297The first pointer points
298to the beginning of the message and the list ends with
299.Dv NULL .
300The limit to the array is specified by
301.Fa lastdnptr .
302A side effect of
303.Fn dn_comp
304is to update the list of pointers for labels inserted into the message
305as the name is compressed.
306If
307.Em dnptr
308is
309.Dv NULL ,
310names are not compressed.
311If
312.Fa lastdnptr
313is
314.Dv NULL ,
315the list of labels is not updated.
316.Pp
317The
318.Fn dn_expand
319entry expands the compressed domain name
320.Fa comp_dn
321to a full domain name.
322The compressed name is contained in a query or reply message;
323.Fa msg
324is a pointer to the beginning of the message.
325The uncompressed name is placed in the buffer indicated by
326.Fa exp_dn
327which is of size
328.Fa length .
329The size of compressed name is returned or \-1 if there was an error.
330.Sh FILES
331.Bl -tag -width "/etc/resolv.confXX"
332.It Pa /etc/resolv.conf
333The configuration file.
334.El
335.Sh SEE ALSO
336.Xr gethostbyname 3 ,
337.Xr resolv.conf 5 ,
338.Xr hostname 7 ,
339.Xr named 8
340.Pp
341.%T RFC 974 ,
342.%T RFC 1032 ,
343.%T RFC 1033 ,
344.%T RFC 1034 ,
345.%T RFC 1035 ,
346.%T RFC 1535
347.Rs
348.%T "Name Server Operations Guide for BIND"
349.Re
350.Sh HISTORY
351The
352.Nm
353function appeared in
354.Bx 4.3 .
diff --git a/src/lib/libc/net/rresvport.c b/src/lib/libc/net/rresvport.c
new file mode 100644
index 0000000000..eee872898b
--- /dev/null
+++ b/src/lib/libc/net/rresvport.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
3 * Copyright (c) 1983, 1993, 1994
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#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: rresvport.c,v 1.7 2005/03/25 13:24:12 otto Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42#include <signal.h>
43#include <fcntl.h>
44#include <netdb.h>
45#include <unistd.h>
46#include <pwd.h>
47#include <errno.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <string.h>
51#include <syslog.h>
52#include <stdlib.h>
53#include <netgroup.h>
54
55int
56rresvport(int *alport)
57{
58 return rresvport_af(alport, AF_INET);
59}
60
61
62int
63rresvport_af(int *alport, int af)
64{
65 struct sockaddr_storage ss;
66 struct sockaddr *sa;
67 u_int16_t *portp;
68 int s;
69
70 bzero(&ss, sizeof ss);
71 sa = (struct sockaddr *)&ss;
72
73 switch (af) {
74 case AF_INET:
75 sa->sa_len = sizeof(struct sockaddr_in);
76 portp = &((struct sockaddr_in *)sa)->sin_port;
77 break;
78 case AF_INET6:
79 sa->sa_len = sizeof(struct sockaddr_in6);
80 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
81 break;
82 default:
83 errno = EPFNOSUPPORT;
84 return (-1);
85 }
86 sa->sa_family = af;
87
88 s = socket(af, SOCK_STREAM, 0);
89 if (s < 0)
90 return (-1);
91
92 *portp = htons(*alport);
93 if (*alport < IPPORT_RESERVED - 1) {
94 if (bind(s, sa, sa->sa_len) >= 0)
95 return (s);
96 if (errno != EADDRINUSE) {
97 (void)close(s);
98 return (-1);
99 }
100 }
101
102 *portp = 0;
103 sa->sa_family = af;
104 if (bindresvport_sa(s, sa) == -1) {
105 (void)close(s);
106 return (-1);
107 }
108 *alport = ntohs(*portp);
109 return (s);
110}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..36ac5a3554
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,215 @@
1/* $OpenBSD: rthdr.c,v 1.7 2005/03/25 13:24:12 otto Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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 <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42size_t
43inet6_rthdr_space(int type, int seg)
44{
45 switch (type) {
46 case IPV6_RTHDR_TYPE_0:
47 if (seg < 1 || seg > 23)
48 return (0);
49 return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
50 sizeof(struct ip6_rthdr0)));
51 default:
52 return (0);
53 }
54}
55
56struct cmsghdr *
57inet6_rthdr_init(void *bp, int type)
58{
59 struct cmsghdr *ch = (struct cmsghdr *)bp;
60 struct ip6_rthdr *rthdr;
61
62 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
63
64 ch->cmsg_level = IPPROTO_IPV6;
65 ch->cmsg_type = IPV6_RTHDR;
66
67 switch (type) {
68 case IPV6_RTHDR_TYPE_0:
69 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
70 bzero(rthdr, sizeof(struct ip6_rthdr0));
71 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
72 return (ch);
73 default:
74 return (NULL);
75 }
76}
77
78int
79inet6_rthdr_add(struct cmsghdr *cmsg, const struct in6_addr *addr, u_int flags)
80{
81 struct ip6_rthdr *rthdr;
82
83 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
84
85 switch (rthdr->ip6r_type) {
86 case IPV6_RTHDR_TYPE_0:
87 {
88 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
89 if (flags != IPV6_RTHDR_LOOSE)
90 return (-1);
91 if (rt0->ip6r0_segleft == 23)
92 return (-1);
93 rt0->ip6r0_segleft++;
94 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
95 sizeof(struct in6_addr));
96 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
97 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
98 break;
99 }
100 default:
101 return (-1);
102 }
103
104 return (0);
105}
106
107int
108inet6_rthdr_lasthop(struct cmsghdr *cmsg, unsigned int flags)
109{
110 struct ip6_rthdr *rthdr;
111
112 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
113
114 switch (rthdr->ip6r_type) {
115 case IPV6_RTHDR_TYPE_0:
116 {
117 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
118 if (flags != IPV6_RTHDR_LOOSE)
119 return (-1);
120 if (rt0->ip6r0_segleft > 23)
121 return (-1);
122 break;
123 }
124 default:
125 return (-1);
126 }
127
128 return (0);
129}
130
131#if 0
132int
133inet6_rthdr_reverse(in, out)
134 const struct cmsghdr *in;
135 struct cmsghdr *out;
136{
137
138 return (-1);
139}
140#endif
141
142int
143inet6_rthdr_segments(const struct cmsghdr *cmsg)
144{
145 struct ip6_rthdr *rthdr;
146
147 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
148
149 switch (rthdr->ip6r_type) {
150 case IPV6_RTHDR_TYPE_0:
151 {
152 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
153
154 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
155 return (-1);
156
157 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
158 }
159
160 default:
161 return (-1);
162 }
163}
164
165struct in6_addr *
166inet6_rthdr_getaddr(struct cmsghdr *cmsg, int index)
167{
168 struct ip6_rthdr *rthdr;
169
170 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
171
172 switch (rthdr->ip6r_type) {
173 case IPV6_RTHDR_TYPE_0:
174 {
175 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
176 int naddr;
177
178 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
179 return NULL;
180 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
181 if (index <= 0 || naddr < index)
182 return NULL;
183 return ((struct in6_addr *)(rt0 + 1)) + index;
184 }
185
186 default:
187 return NULL;
188 }
189}
190
191int
192inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index)
193{
194 struct ip6_rthdr *rthdr;
195
196 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
197
198 switch (rthdr->ip6r_type) {
199 case IPV6_RTHDR_TYPE_0:
200 {
201 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
202 int naddr;
203
204 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
205 return (-1);
206 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
207 if (index < 0 || naddr < index)
208 return (-1);
209 return IPV6_RTHDR_LOOSE;
210 }
211
212 default:
213 return (-1);
214 }
215}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
new file mode 100644
index 0000000000..f28933369c
--- /dev/null
+++ b/src/lib/libc/net/send.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: send.c,v 1.4 2005/03/25 13:24:12 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <stddef.h>
38
39ssize_t
40send(int s, const void *msg, size_t len, int flags)
41{
42 return (sendto(s, msg, len, flags, NULL, 0));
43}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
new file mode 100644
index 0000000000..c0eae942ca
--- /dev/null
+++ b/src/lib/libc/net/sethostent.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: sethostent.c,v 1.8 2005/03/30 02:58:28 tedu Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/nameser.h>
37#include <netdb.h>
38#include <resolv.h>
39
40#include "thread_private.h"
41
42void
43sethostent(int stayopen)
44{
45 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
46
47 if (_res_init(0) == -1)
48 return;
49 if (stayopen)
50 _resp->options |= RES_STAYOPEN | RES_USEVC;
51}
52
53void
54endhostent(void)
55{
56 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
57
58 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
59 res_close();
60}
diff --git a/src/lib/libc/net/vars6.c b/src/lib/libc/net/vars6.c
new file mode 100644
index 0000000000..a22d49d047
--- /dev/null
+++ b/src/lib/libc/net/vars6.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: vars6.c,v 1.2 2003/05/10 10:56:47 jmc Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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 <sys/types.h>
33#include <netinet/in.h>
34
35/*
36 * Definitions of some constant IPv6 addresses.
37 */
38const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
39const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
40const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
41const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
42
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
new file mode 100644
index 0000000000..1d5ba5c9bd
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,71 @@
1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $
2
3# stdlib sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c l64a.c llabs.c lsearch.c malloc.c \
9 merge.c multibyte.c putenv.c qsort.c radixsort.c rand.c random.c \
10 realpath.c setenv.c strtod.c strtol.c strtoll.c strtonum.c strtoul.c \
11 strtoull.c system.c \
12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c
14
15.if (${MACHINE_ARCH} == "m68k")
16SRCS+= abs.S div.c labs.c ldiv.c
17LSRCS+= abs.c
18.elif (${MACHINE_ARCH} == "i386")
19SRCS+= abs.S div.S labs.S ldiv.S
20LSRCS+= abs.c div.c labs.c ldiv.c
21.elif (${MACHINE_ARCH} == "ns32k")
22SRCS+= abs.S div.c labs.c ldiv.c
23LSRCS+= abs.c
24.elif (${MACHINE_ARCH} == "tahoe")
25SRCS+= abs.S div.c labs.c ldiv.c
26LSRCS+= abs.c
27.elif (${MACHINE_ARCH} == "vax")
28SRCS+= abs.c div.c labs.c ldiv.c
29.elif (${MACHINE_ARCH} == "alpha")
30# XXX should be .S's
31SRCS+= abs.c div.c labs.c ldiv.c
32.else
33SRCS+= abs.c div.c labs.c ldiv.c
34.endif
35
36.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
37SRCS+= insque.S remque.S
38.else
39SRCS+= insque.c remque.c
40.endif
41
42MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
43 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
44 getsubopt.3 hcreate.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 qabs.3 \
45 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
46 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3
47
48MLINKS+=exit.3 _Exit.3
49MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
50MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
51MLINKS+=getopt_long.3 getopt_long_only.3
52MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
53MLINKS+=insque.3 remque.3
54MLINKS+=labs.3 llabs.3
55MLINKS+=lsearch.3 lfind.3
56MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
57MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
58MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
59MLINKS+=radixsort.3 sradixsort.3
60MLINKS+=rand.3 srand.3 rand.3 rand_r.3
61MLINKS+=random.3 initstate.3 random.3 setstate.3
62MLINKS+=random.3 srandom.3 random.3 srandomdev.3
63MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
64MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
65MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
66MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
67MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
68MLINKS+=tsearch.3 tfind.3
69MLINKS+=tsearch.3 tdelete.3
70MLINKS+=tsearch.3 twalk.3
71MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_Exit.c b/src/lib/libc/stdlib/_Exit.c
new file mode 100644
index 0000000000..784015a21d
--- /dev/null
+++ b/src/lib/libc/stdlib/_Exit.c
@@ -0,0 +1,26 @@
1/* $OpenBSD: _Exit.c,v 1.1 2004/05/03 17:21:13 millert Exp $ */
2
3/*
4 * Placed in the public domain by Todd C. Miller on January 21, 2004.
5 */
6
7#if defined(LIBC_SCCS) && !defined(lint)
8static char *rcsid = "$OpenBSD: _Exit.c,v 1.1 2004/05/03 17:21:13 millert Exp $";
9#endif /* LIBC_SCCS and not lint */
10
11#include <stdlib.h>
12#include <unistd.h>
13
14/*
15 * _Exit() is the ISO/ANSI C99 equivalent of the POSIX _exit() function.
16 * No atexit() handlers are called and no signal handlers are run.
17 * Whether or not stdio buffers are flushed or temporary files are removed
18 * is implementation-dependent. As such it is safest to *not* flush
19 * stdio buffers or remove temporary files. This is also consistent
20 * with most other implementations.
21 */
22void
23_Exit(int status)
24{
25 _exit(status);
26}
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
new file mode 100644
index 0000000000..fed7372f68
--- /dev/null
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -0,0 +1,50 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: _rand48.c,v 1.2 1996/08/19 08:33:19 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20unsigned short __rand48_seed[3] = {
21 RAND48_SEED_0,
22 RAND48_SEED_1,
23 RAND48_SEED_2
24};
25unsigned short __rand48_mult[3] = {
26 RAND48_MULT_0,
27 RAND48_MULT_1,
28 RAND48_MULT_2
29};
30unsigned short __rand48_add = RAND48_ADD;
31
32void
33__dorand48(unsigned short xseed[3])
34{
35 unsigned long accu;
36 unsigned short temp[2];
37
38 accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
39 (unsigned long) __rand48_add;
40 temp[0] = (unsigned short) accu; /* lower 16 bits */
41 accu >>= sizeof(unsigned short) * 8;
42 accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
43 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
44 temp[1] = (unsigned short) accu; /* middle 16 bits */
45 accu >>= sizeof(unsigned short) * 8;
46 accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
47 xseed[0] = temp[0];
48 xseed[1] = temp[1];
49 xseed[2] = (unsigned short) accu;
50}
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..f2957a7ad4
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.9 2005/02/25 03:12:44 cloder Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd August 17, 1997
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.Fd #include <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 WARNINGS
112The value returned by
113.Fn l64a
114is a pointer into a static buffer, the contents of which
115will be overwritten by subsequent calls.
116.Pp
117The value returned by
118.Fn a64l
119may be incorrect if the value is too large; for that reason, only strings
120that resulted from a call to
121.Fn l64a
122should be used to call
123.Fn a64l .
124.Pp
125If a long integer is larger than 32 bits, only the low-order
12632 bits are used.
127.Sh STANDARDS
128The
129.Fn a64l
130and
131.Fn l64a
132functions conform to
133.St -xpg4.2 .
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
new file mode 100644
index 0000000000..518bdb64f9
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.c
@@ -0,0 +1,45 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: a64l.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13long
14a64l(const char *s)
15{
16 long value, digit, shift;
17 int i;
18
19 if (s == NULL) {
20 errno = EINVAL;
21 return(-1L);
22 }
23
24 value = 0;
25 shift = 0;
26 for (i = 0; *s && i < 6; i++, s++) {
27 if (*s >= '.' && *s <= '/')
28 digit = *s - '.';
29 else if (*s >= '0' && *s <= '9')
30 digit = *s - '0' + 2;
31 else if (*s >= 'A' && *s <= 'Z')
32 digit = *s - 'A' + 12;
33 else if (*s >= 'a' && *s <= 'z')
34 digit = *s - 'a' + 38;
35 else {
36 errno = EINVAL;
37 return(-1L);
38 }
39
40 value |= digit << shift;
41 shift += 6;
42 }
43
44 return(value);
45}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
new file mode 100644
index 0000000000..d411b859eb
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.3
@@ -0,0 +1,63 @@
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.7 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ABORT 3
36.Os
37.Sh NAME
38.Nm abort
39.Nd cause abnormal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn abort void
44.Sh DESCRIPTION
45The
46.Fn abort
47function causes abnormal program termination to occur, unless the signal
48.Dv SIGABRT
49is being caught and the signal handler does not return.
50.Pp
51Any open streams are flushed and closed.
52.Sh RETURN VALUES
53The
54.Fn abort
55function never returns.
56.Sh SEE ALSO
57.Xr sigaction 2 ,
58.Xr exit 3
59.Sh STANDARDS
60The
61.Fn abort
62function conforms to
63.St -p1003.1-90 .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
new file mode 100644
index 0000000000..2430c124f9
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: abort.c,v 1.13 2004/01/20 19:35:17 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <signal.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include "thread_private.h"
38#include "atexit.h"
39
40void
41abort(void)
42{
43 struct atexit *p = __atexit;
44 static int cleanup_called = 0;
45 sigset_t mask;
46
47
48 sigfillset(&mask);
49 /*
50 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway.
52 */
53 sigdelset(&mask, SIGABRT);
54 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
55
56 /*
57 * POSIX requires we flush stdio buffers on abort
58 */
59 if (cleanup_called == 0) {
60 while (p != NULL && p->next != NULL)
61 p = p->next;
62 if (p != NULL && p->fns[0] != NULL) {
63 cleanup_called = 1;
64 (*p->fns[0])();
65 }
66 }
67
68 (void)kill(getpid(), SIGABRT);
69
70 /*
71 * if SIGABRT ignored, or caught and the handler returns, do
72 * it again, only harder.
73 */
74 (void)signal(SIGABRT, SIG_DFL);
75 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
76 (void)kill(getpid(), SIGABRT);
77 _exit(1);
78}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..f0a6b8a23a
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: abs.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ABS 3
36.Os
37.Sh NAME
38.Nm abs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft int
43.Fn abs "int j"
44.Sh DESCRIPTION
45The
46.Fn abs
47function computes the absolute value of the integer
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn abs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr cabs 3 ,
55.Xr floor 3 ,
56.Xr hypot 3 ,
57.Xr labs 3 ,
58.Xr math 3
59.Sh STANDARDS
60The
61.Fn abs
62function conforms to
63.St -ansiC .
64.Sh BUGS
65The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
new file mode 100644
index 0000000000..a471ab3a1e
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: abs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37abs(int j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
new file mode 100644
index 0000000000..4136dc405c
--- /dev/null
+++ b/src/lib/libc/stdlib/alloca.3
@@ -0,0 +1,80 @@
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.10 2003/06/02 20:18:37 millert Exp $
29.\"
30.Dd May 2, 1991
31.Dt ALLOCA 3
32.Os
33.Sh NAME
34.Nm alloca
35.Nd memory allocator
36.Sh SYNOPSIS
37.Fd #include <stdlib.h>
38.Ft void *
39.Fn alloca "size_t size"
40.Sh DESCRIPTION
41The
42.Fn alloca
43function allocates
44.Fa size
45bytes of space in the stack frame of the caller.
46This temporary space is automatically freed on return.
47.Sh RETURN VALUES
48The
49.Fn alloca
50function returns a pointer to the beginning of the allocated space.
51.Sh SEE ALSO
52.Xr pagesize 1 ,
53.Xr brk 2 ,
54.Xr calloc 3 ,
55.Xr malloc 3 ,
56.Xr realloc 3
57.Sh BUGS
58The
59.Fn alloca
60function is machine dependent; its use is discouraged.
61.\" .Sh HISTORY
62.\" The
63.\" .Fn alloca
64.\" function appeared in
65.\" .Bx ?? .
66.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
67.\" The first man page (or link to a man page that I can find at the
68.\" moment is 4.3...
69.Pp
70The
71.Fn alloca
72function is slightly unsafe because it cannot ensure that the pointer
73returned points to a valid and usable block of memory.
74The allocation made may exceed the bounds of the stack, or even go
75further into other objects in memory, and
76.Fn alloca
77cannot determine such an error.
78Avoid
79.Fn alloca
80with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
new file mode 100644
index 0000000000..c8d4ce63d5
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.3
@@ -0,0 +1,71 @@
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.5 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
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.Fd #include <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.Sh RETURN VALUES
58.Rv -std atexit
59.Sh ERRORS
60.Bl -tag -width Er
61.It Bq Er ENOMEM
62No memory was available to add the function to the list.
63The existing list of functions is unmodified.
64.El
65.Sh SEE ALSO
66.Xr exit 3
67.Sh STANDARDS
68The
69.Fn atexit
70function conforms to
71.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000000..4fd2c57318
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (c) 2002 Daniel Hartmeier
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: atexit.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/types.h>
36#include <sys/mman.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include "atexit.h"
40
41int __atexit_invalid = 1;
42struct atexit *__atexit;
43
44/*
45 * Function pointers are stored in a linked list of pages. The list
46 * is initially empty, and pages are allocated on demand. The first
47 * function pointer in the first allocated page (the last one in
48 * the linked list) is reserved for the cleanup function.
49 *
50 * Outside the following two functions, all pages are mprotect()'ed
51 * to prevent unintentional/malicious corruption.
52 *
53 * The free(malloc(1)) is a workaround causing malloc_init() to
54 * ensure that malloc.c gets the first mmap() call for its sbrk()
55 * games.
56 */
57
58/*
59 * Register a function to be performed at exit.
60 */
61int
62atexit(void (*fn)(void))
63{
64 struct atexit *p = __atexit;
65 int pgsize = getpagesize();
66
67 if (pgsize < sizeof(*p))
68 return (-1);
69 if (p != NULL) {
70 if (p->ind + 1 >= p->max)
71 p = NULL;
72 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
73 return (-1);
74 }
75 if (p == NULL) {
76 if (__atexit_invalid) {
77 free(malloc(1));
78 __atexit_invalid = 0;
79 }
80 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
81 MAP_ANON | MAP_PRIVATE, -1, 0);
82 if (p == MAP_FAILED)
83 return (-1);
84 if (__atexit == NULL) {
85 p->fns[0] = NULL;
86 p->ind = 1;
87 } else
88 p->ind = 0;
89 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
90 sizeof(p->fns[0]);
91 p->next = __atexit;
92 __atexit = p;
93 }
94 p->fns[p->ind++] = fn;
95 if (mprotect(p, pgsize, PROT_READ))
96 return (-1);
97 return (0);
98}
99
100/*
101 * Register the cleanup function
102 */
103void
104__atexit_register_cleanup(void (*fn)(void))
105{
106 struct atexit *p = __atexit;
107 int pgsize = getpagesize();
108
109 if (pgsize < sizeof(*p))
110 return;
111 while (p != NULL && p->next != NULL)
112 p = p->next;
113 if (p == NULL) {
114 if (__atexit_invalid) {
115 free(malloc(1));
116 __atexit_invalid = 0;
117 }
118 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
119 MAP_ANON | MAP_PRIVATE, -1, 0);
120 if (p == MAP_FAILED)
121 return;
122 p->ind = 1;
123 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
124 sizeof(p->fns[0]);
125 p->next = NULL;
126 __atexit = p;
127 } else {
128 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
129 return;
130 }
131 p->fns[0] = fn;
132 mprotect(p, pgsize, PROT_READ);
133}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000000..21b0c2e532
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.h
@@ -0,0 +1,41 @@
1/* $OpenBSD: atexit.h,v 1.6 2003/07/31 07:08:42 deraadt 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 void (*fns[1])(void); /* the table itself */
38};
39
40extern int __atexit_invalid;
41extern struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000000..c60b9e9fd7
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.3
@@ -0,0 +1,69 @@
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.4 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOF 3
36.Os
37.Sh NAME
38.Nm atof
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft double
45.Fn atof "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atof
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtod(nptr, (char **)NULL);
58.Ed
59.Sh SEE ALSO
60.Xr atoi 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtoul 3
65.Sh STANDARDS
66The
67.Fn atof
68function conforms to
69.St -ansiC .
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
new file mode 100644
index 0000000000..2724530231
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atof.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36double
37atof(const char *ascii)
38{
39 return(strtod(ascii, (char **)NULL));
40}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000000..dee8b637a3
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.3
@@ -0,0 +1,86 @@
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.8 2004/08/22 21:47:41 jaredy Exp $
33.\"
34.Dd June 4, 1993
35.Dt ATOI 3
36.Os
37.Sh NAME
38.Nm atoi
39.Nd convert
40.Tn ASCII
41string to integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft int
45.Fn atoi "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoi
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57(int)strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtonum 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoi
69function conforms to
70.St -ansiC .
71.Sh CAVEATS
72.Nm
73does no overflow checking, handles unsigned numbers poorly,
74and handles strings containing trailing extra characters
75(like
76.Dq "123abc" )
77poorly.
78Careful use of
79.Xr strtol 3
80and
81.Xr strtoul 3
82can alleviate these problems,
83but
84.Xr strtonum 3
85can be used to convert numbers from strings much more safely
86and easily.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000000..ea821ced3d
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atoi.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37atoi(const char *str)
38{
39 return((int)strtol(str, (char **)NULL, 10));
40}
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
new file mode 100644
index 0000000000..80e54c892d
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atol.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOL 3
36.Os
37.Sh NAME
38.Nm atol
39.Nd convert
40.Tn ASCII
41string to long integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft long
45.Fn atol "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atol
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atoll 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atol
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
new file mode 100644
index 0000000000..38236b556c
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atol.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37atol(const char *str)
38{
39 return(strtol(str, (char **)NULL, 10));
40}
diff --git a/src/lib/libc/stdlib/atoll.3 b/src/lib/libc/stdlib/atoll.3
new file mode 100644
index 0000000000..40584e9d47
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atoll.3,v 1.3 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOLL 3
36.Os
37.Sh NAME
38.Nm atoll
39.Nd convert
40.Tn ASCII
41string to long long integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft long long
45.Fn atoll "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoll
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtoll(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atol 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoll
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000000..6786b62e1a
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atoll.c,v 1.2 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long long
37atoll(str)
38 const char *str;
39{
40 return(strtoll(str, (char **)NULL, 10));
41}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
new file mode 100644
index 0000000000..d1dd9173db
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -0,0 +1,84 @@
1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: bsearch.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd April 19, 1994
35.Dt BSEARCH 3
36.Os
37.Sh NAME
38.Nm bsearch
39.Nd binary search of a sorted table
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void *
43.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar) (const void *, const void *)"
44.Sh DESCRIPTION
45The
46.Fn bsearch
47function searches an array of
48.Fa nmemb
49objects, the initial member of which is
50pointed to by
51.Fa base ,
52for a member that matches the object pointed to by
53.Fa key .
54The size of each member of the array is specified by
55.Fa size .
56.Pp
57The contents of the array should be in ascending sorted order according
58to the comparison function referenced by
59.Fa compar .
60The
61.Fa compar
62routine is expected to have two arguments which point to the
63.Fa key
64object and to an array member, in that order, and should return an integer
65less than, equal to, or greater than zero if the
66.Fa key
67object is found, respectively, to be less than, to match, or be
68greater than the array member.
69.Sh RETURN VALUES
70The
71.Fn bsearch
72function returns a pointer to a matching member of the array, or a null
73pointer if no match is found.
74If two members compare as equal, which member is matched is unspecified.
75.Sh SEE ALSO
76.Xr db 3 ,
77.Xr lsearch 3 ,
78.Xr qsort 3 ,
79.Xr tsearch 3
80.Sh STANDARDS
81The
82.Fn bsearch
83function conforms to
84.St -ansiC .
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
new file mode 100644
index 0000000000..109211da92
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: bsearch.c,v 1.5 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36/*
37 * Perform a binary search.
38 *
39 * The code below is a bit sneaky. After a comparison fails, we
40 * divide the work in half by moving either left or right. If lim
41 * is odd, moving left simply involves halving lim: e.g., when lim
42 * is 5 we look at item 2, so we change lim to 2 so that we will
43 * look at items 0 & 1. If lim is even, the same applies. If lim
44 * is odd, moving right again involes halving lim, this time moving
45 * the base up one item past p: e.g., when lim is 5 we change base
46 * to item 3 and make lim 2 so that we will look at items 3 and 4.
47 * If lim is even, however, we have to shrink it by one before
48 * halving: e.g., when lim is 4, we still looked at item 2, so we
49 * have to make lim 3, then halve, obtaining 1, so that we will only
50 * look at item 3.
51 */
52void *
53bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
54 int (*compar)(const void *, const void *))
55{
56 const char *base = base0;
57 int lim, cmp;
58 const void *p;
59
60 for (lim = nmemb; lim != 0; lim >>= 1) {
61 p = base + (lim >> 1) * size;
62 cmp = (*compar)(key, p);
63 if (cmp == 0)
64 return ((void *)p);
65 if (cmp > 0) { /* key > p: move right */
66 base = (char *)p + size;
67 lim--;
68 } /* else move left */
69 }
70 return (NULL);
71}
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
new file mode 100644
index 0000000000..7aabed235f
--- /dev/null
+++ b/src/lib/libc/stdlib/calloc.c
@@ -0,0 +1,53 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: calloc.c,v 1.9 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36#include <limits.h>
37#include <errno.h>
38
39void *
40calloc(size_t num, size_t size)
41{
42 void *p;
43
44 if (num && size && SIZE_T_MAX / num < size) {
45 errno = ENOMEM;
46 return NULL;
47 }
48 size *= num;
49 p = malloc(size);
50 if (p)
51 memset(p, 0, size);
52 return(p);
53}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..db1fa56039
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,44 @@
1/* $OpenBSD: cfree.c,v 1.4 2005/03/30 18:51:49 pat Exp $ */
2
3/*
4 * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#if defined(LIBC_SCCS) && !defined(lint)
29static char rcsid[] = "$OpenBSD: cfree.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
30#endif /* LIBC_SCCS and not lint */
31
32#include <sys/cdefs.h>
33#include <stdlib.h>
34
35#ifdef __indr_reference
36__indr_reference(free, cfree);
37#else
38
39void
40cfree(void *p)
41{
42 free(p);
43}
44#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
new file mode 100644
index 0000000000..a75614310e
--- /dev/null
+++ b/src/lib/libc/stdlib/div.3
@@ -0,0 +1,63 @@
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.7 2004/01/23 23:08:46 jmc Exp $
31.\"
32.Dd April 19, 1991
33.Dt DIV 3
34.Os
35.Sh NAME
36.Nm div
37.Nd return quotient and remainder from division
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft div_t
41.Fn div "int num" "int denom"
42.Sh DESCRIPTION
43The
44.Fn div
45function computes the value
46.Fa num Ns / Ns Fa denom
47and returns the quotient and remainder in a structure named
48.Fa div_t
49that contains two
50.Li int
51members named
52.Fa quot
53and
54.Fa rem .
55.Sh SEE ALSO
56.Xr ldiv 3 ,
57.Xr math 3 ,
58.Xr qdiv 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
new file mode 100644
index 0000000000..32c53dff03
--- /dev/null
+++ b/src/lib/libc/stdlib/div.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: div.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* div_t */
38
39div_t
40div(int num, int denom)
41{
42 div_t r;
43
44 r.quot = num / denom;
45 r.rem = num % denom;
46 /*
47 * The ANSI standard says that |r.quot| <= |n/d|, where
48 * n/d is to be computed in infinite precision. In other
49 * words, we should always truncate the quotient towards
50 * 0, never -infinity.
51 *
52 * Machine division and remainer may work either way when
53 * one or both of n or d is negative. If only one is
54 * negative and r.quot has been truncated towards -inf,
55 * r.rem will have the same sign as denom and the opposite
56 * sign of num; if both are negative and r.quot has been
57 * truncated towards -inf, r.rem will be positive (will
58 * have the opposite sign of num). These are considered
59 * `wrong'.
60 *
61 * If both are num and denom are positive, r will always
62 * be positive.
63 *
64 * This all boils down to:
65 * if num >= 0, but r.rem < 0, we got the wrong answer.
66 * In that case, to get the right answer, add 1 to r.quot and
67 * subtract denom from r.rem.
68 */
69 if (num >= 0 && r.rem < 0) {
70 r.quot++;
71 r.rem -= denom;
72 }
73 return (r);
74}
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
new file mode 100644
index 0000000000..02886d5b62
--- /dev/null
+++ b/src/lib/libc/stdlib/drand48.c
@@ -0,0 +1,26 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: drand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22double
23drand48(void)
24{
25 return erand48(__rand48_seed);
26}
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..689cb1c6f9
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.7 2004/01/25 14:48:32 jmc Exp $
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.\" Sponsored in part by the Defense Advanced Research Projects
18.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
19.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
20.\"
21.Dd December 1, 2002
22.Dt ECVT 3
23.Os
24.Sh NAME
25.Nm ecvt ,
26.Nm fcvt ,
27.Nm gcvt
28.Nd convert double to
29.Tn ASCII
30string
31.Sh SYNOPSIS
32.Fd #include <stdlib.h>
33.Ft char *
34.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
35.Ft char *
36.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
37.Ft char *
38.Fn gcvt "double value" "int ndigit" "char *buf"
39.Sh DESCRIPTION
40.Bf -symbolic
41These functions are provided for compatibility with legacy code.
42New code should use the
43.Xr snprintf 3
44function for improved safety and portability.
45.Ef
46.Pp
47The
48.Fn ecvt ,
49.Fn fcvt
50and
51.Fn gcvt
52functions convert the double precision floating-point number
53.Fa value
54to a NUL-terminated
55.Tn ASCII
56string.
57.Pp
58The
59.Fn ecvt
60function converts
61.Fa value
62to a NUL-terminated string of exactly
63.Fa ndigit
64digits and returns a pointer to that string.
65The result is padded with zeroes from left to right as needed.
66There are no leading zeroes unless
67.Fa value
68itself is 0.
69The least significant digit is rounded in an implementation-dependent manner.
70The position of the decimal point relative to the beginning of the string
71is stored in
72.Fa decpt .
73A negative value indicates that the decimal point is located
74to the left of the returned digits (this occurs when there is no
75whole number component to
76.Fa value ) .
77If
78.Fa value
79is zero, it is unspecified whether the integer pointed to by
80.Fa decpt
81will be 0 or 1.
82The decimal point itself is not included in the returned string.
83If the sign of the result is negative, the integer pointed to by
84.Fa sign
85is non-zero; otherwise, it is 0.
86.Pp
87If the converted value is out of range or is not representable,
88the contents of the returned string are unspecified.
89.Pp
90The
91.Fn fcvt
92function is identical to
93.Fn ecvt
94with the exception that
95.Fa ndigit
96specifies the number of digits after the decimal point (zero-padded as
97needed).
98.Pp
99The
100.Fn gcvt
101function converts
102.Fa value
103to a NUL-terminated string similar to the %g
104.Xr printf 3
105format specifier and stores the result in
106.Fa buf .
107It produces
108.Fa ndigit
109significant digits similar to the %f
110.Xr printf 3
111format specifier where possible.
112If
113.Fa ndigit
114does allow sufficient precision, the result is stored in
115exponential notation similar to the %e
116.Xr printf 3
117format specifier.
118If
119.Fa value
120is less than zero,
121.Fa buf
122will be prefixed with a minus sign.
123A decimal point is included in the returned string if
124.Fa value
125is not a whole number.
126Unlike the
127.Fn ecvt
128and
129.Fn fcvt
130functions,
131.Fa buf
132is not zero-padded.
133.Sh RETURN VALUES
134The
135.Fn ecvt ,
136.Fn fcvt
137and
138.Fn gcvt
139functions return a NUL-terminated string representation of
140.Fa value .
141.Sh WARNINGS
142The
143.Fn ecvt
144and
145.Fn fcvt
146functions return a pointer to internal storage space that will be
147overwritten by subsequent calls to either function.
148.Pp
149The maximum possible precision of the return value is limited by the
150precision of a double and may not be the same on all architectures.
151.Pp
152The
153.Xr snprintf 3
154function is preferred over these functions for new code.
155.Sh SEE ALSO
156.Xr printf 3 ,
157.Xr strtod 3
158.Sh STANDARDS
159The
160.Fn ecvt ,
161.Fn fcvt
162and
163.Fn gcvt
164functions conform to
165.St -p1003.1-2001 .
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..657c531808
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,103 @@
1/* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#if defined(LIBC_SCCS) && !defined(lint)
24static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
25#endif /* LIBC_SCCS and not lint */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31extern char *__dtoa(double, int, int, int *, int *, char **);
32static char *__cvt(double, int, int *, int *, int, int);
33
34static char *
35__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
36{
37 static char *s;
38 char *p, *rve;
39 size_t siz;
40
41 if (ndigit == 0) {
42 *sign = value < 0.0;
43 *decpt = 0;
44 return ("");
45 }
46
47 if (s) {
48 free(s);
49 s = NULL;
50 }
51
52 if (ndigit < 0)
53 siz = -ndigit + 1;
54 else
55 siz = ndigit + 1;
56
57
58 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
59 if (value == 0.0) {
60 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
61 *sign = 0;
62 if ((rve = s = (char *)malloc(siz)) == NULL)
63 return(NULL);
64 *rve++ = '0';
65 *rve = '\0';
66 } else {
67 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
68 if (*decpt == 9999) {
69 /* Nan or Infinity */
70 *decpt = 0;
71 return(p);
72 }
73 /* make a local copy and adjust rve to be in terms of s */
74 if (pad && fmode)
75 siz += *decpt;
76 if ((s = (char *)malloc(siz)) == NULL)
77 return(NULL);
78 (void) strlcpy(s, p, siz);
79 rve = s + (rve - p);
80 }
81
82 /* Add trailing zeros (unless we got NaN or Inf) */
83 if (pad && *decpt != 9999) {
84 siz -= rve - s;
85 while (--siz)
86 *rve++ = '0';
87 *rve = '\0';
88 }
89
90 return(s);
91}
92
93char *
94ecvt(double value, int ndigit, int *decpt, int *sign)
95{
96 return(__cvt(value, ndigit, decpt, sign, 0, 1));
97}
98
99char *
100fcvt(double value, int ndigit, int *decpt, int *sign)
101{
102 return(__cvt(value, ndigit, decpt, sign, 1, 1));
103}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
new file mode 100644
index 0000000000..b92dacffcc
--- /dev/null
+++ b/src/lib/libc/stdlib/erand48.c
@@ -0,0 +1,27 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: erand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20double
21erand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ldexp((double) xseed[0], -48) +
25 ldexp((double) xseed[1], -32) +
26 ldexp((double) xseed[2], -16);
27}
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000000..fa233ac75f
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.3
@@ -0,0 +1,114 @@
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.10 2004/05/03 17:21:13 millert Exp $
33.\"
34.Dd January 21, 2004
35.Dt EXIT 3
36.Os
37.Sh NAME
38.Nm exit, _Exit
39.Nd perform normal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn exit "int status"
44.Ft void
45.Fn _Exit "int status"
46.Sh DESCRIPTION
47The
48.Fn exit
49and
50.Fn _Exit
51functions terminate a process.
52.Pp
53Before termination,
54.Fn exit
55performs the following operations in the order listed:
56.Bl -enum -offset indent
57.It
58Call the functions registered with the
59.Xr atexit 3
60function, in the reverse order of their registration.
61.It
62Flush all open output streams.
63.It
64Close all open streams.
65.It
66Unlink all files created with the
67.Xr tmpfile 3
68function.
69.El
70.Pp
71The
72.Fn _Exit
73function terminates without calling the functions registered with the
74.Xr atexit 3
75function.
76The
77.Ox
78implementation of
79.Fn _Exit
80does not flush open output streams or unlink files created with the
81.Xr tmpfile 3
82function.
83However, this behavior is implementation-specific.
84.Pp
85Lastly,
86.Fn exit
87and
88.Fn _Exit
89call
90.Xr _exit 2 .
91Note that typically
92.Xr _exit 2
93only passes the lower 8 bits of
94.Fa status
95on to the parent, thus negative values have less meaning.
96.Sh RETURN VALUES
97The
98.Fn exit
99and
100.Fn _Exit
101functions never return.
102.Sh SEE ALSO
103.Xr _exit 2 ,
104.Xr atexit 3 ,
105.Xr intro 3 ,
106.Xr sysexits 3 ,
107.Xr tmpfile 3
108.Sh STANDARDS
109The
110.Fn exit
111and
112.Fn _Exit
113functions conform to
114.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000000..a0960e83c4
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,72 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: exit.c,v 1.10 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/mman.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include "atexit.h"
39#include "thread_private.h"
40
41/*
42 * This variable is zero until a process has created a thread.
43 * It is used to avoid calling locking functions in libc when they
44 * are not required. By default, libc is intended to be(come)
45 * thread-safe, but without a (significant) penalty to non-threaded
46 * processes.
47 */
48int __isthreaded = 0;
49
50/*
51 * Exit, flushing stdio buffers if necessary.
52 */
53void
54exit(int status)
55{
56 struct atexit *p, *q;
57 int n, pgsize = getpagesize();
58
59 if (!__atexit_invalid) {
60 p = __atexit;
61 while (p != NULL) {
62 for (n = p->ind; --n >= 0;)
63 if (p->fns[n] != NULL)
64 (*p->fns[n])();
65 q = p;
66 p = p->next;
67 munmap(q, pgsize);
68 }
69 }
70 /* cleanup, if registered, was called through fns[0] in the last page */
71 _exit(status);
72}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..9fd664b346
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,99 @@
1/* $OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#if defined(LIBC_SCCS) && !defined(lint)
24static char rcsid[] = "$OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $";
25#endif /* LIBC_SCCS and not lint */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31extern char *__dtoa(double, int, int, int *, int *, char **);
32
33char *
34gcvt(double value, int ndigit, char *buf)
35{
36 char *digits, *dst, *src;
37 int i, decpt, sign;
38
39 if (ndigit == 0) {
40 buf[0] = '\0';
41 return (buf);
42 }
43
44 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
45 if (decpt == 9999) {
46 /* Infinity or NaN, assume buffer is at least ndigit long. */
47 strlcpy(buf, digits, ndigit + 1);
48 return (buf);
49 }
50
51 dst = buf;
52 if (sign)
53 *dst++ = '-';
54
55 if (decpt < 0 || decpt > ndigit) {
56 /* exponential format */
57 if (--decpt < 0) {
58 sign = 1;
59 decpt = -decpt;
60 } else
61 sign = 0;
62 for (src = digits; *src != '\0'; )
63 *dst++ = *src++;
64 *dst++ = 'e';
65 if (sign)
66 *dst++ = '-';
67 else
68 *dst++ = '+';
69 if (decpt < 10) {
70 *dst++ = '0';
71 *dst++ = '0' + decpt;
72 *dst = '\0';
73 } else {
74 /* XXX - optimize */
75 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
76 sign /= 10;
77 while (decpt != 0) {
78 dst[i--] = '0' + decpt % 10;
79 decpt /= 10;
80 }
81 }
82 } else {
83 /* standard format */
84 for (i = 0, src = digits; i < decpt; i++) {
85 if (*src != '\0')
86 *dst++ = *src++;
87 else
88 *dst++ = '0';
89 }
90 if (*src != '\0') {
91 *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
92 for (i = decpt; digits[i] != '\0'; i++) {
93 *dst++ = digits[i];
94 }
95 }
96 *dst = '\0';
97 }
98 return (buf);
99}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000000..054004e1d8
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.3
@@ -0,0 +1,142 @@
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.9 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd December 11, 1993
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.Fd #include <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 "const char *string"
51.Ft void
52.Fn unsetenv "const char *name"
53.Sh DESCRIPTION
54These functions set, unset, and fetch environment variables from the host
55.Em environment list .
56For compatibility with differing environment conventions, the given arguments
57.Fa name
58and
59.Fa value
60may be appended and prepended, respectively, with an equal sign
61.Dq Li \&= .
62.Pp
63The
64.Fn getenv
65function obtains the current value of the environment variable,
66.Fa name .
67If the variable
68.Fa name
69is not in the current environment, a null pointer is returned.
70.Pp
71The
72.Fn setenv
73function inserts or resets the environment variable
74.Fa name
75in the current environment list.
76If the variable
77.Fa name
78does not exist in the list, it is inserted with the given
79.Fa value .
80If the variable does exist, the argument
81.Fa overwrite
82is tested; if
83.Fa overwrite
84is zero, the variable is not reset, otherwise it is reset to the given
85.Fa value .
86.Pp
87The
88.Fn putenv
89function takes an argument of the form
90.Ar name Ns = Ns Ar value
91and is equivalent to:
92.Bd -literal -offset indent
93setenv(name, value, 1);
94.Ed
95.Pp
96The
97.Fn unsetenv
98function deletes all instances of the variable name pointed to by
99.Fa name
100from the list.
101.Sh RETURN VALUES
102The functions
103.Fn setenv
104and
105.Fn putenv
106return zero if successful; otherwise the global variable
107.Va errno
108is set to indicate the error and \-1 is returned.
109.Pp
110If
111.Fn getenv
112is successful, the string returned should be considered read-only.
113.Sh ERRORS
114.Bl -tag -width [ENOMEM]
115.It Bq Er ENOMEM
116The function
117.Fn setenv
118or
119.Fn putenv
120failed because they were unable to allocate memory for the environment.
121.El
122.Sh SEE ALSO
123.Xr csh 1 ,
124.Xr sh 1 ,
125.Xr execve 2 ,
126.Xr environ 7
127.Sh STANDARDS
128The
129.Fn getenv
130function conforms to
131.St -ansiC .
132.Sh HISTORY
133The functions
134.Fn setenv
135and
136.Fn unsetenv
137appeared in
138.At v7 .
139The
140.Fn putenv
141function appeared in
142.Bx 4.3 Reno .
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
new file mode 100644
index 0000000000..7e4d6b91a9
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright (c) 1987, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: getenv.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37char *__findenv(const char *name, int *offset);
38
39/*
40 * __findenv --
41 * Returns pointer to value associated with name, if any, else NULL.
42 * Sets offset to be the offset of the name/value combination in the
43 * environmental array, for use by setenv(3) and unsetenv(3).
44 * Explicitly removes '=' in argument name.
45 *
46 * This routine *should* be a static; don't use it.
47 */
48char *
49__findenv(const char *name, int *offset)
50{
51 extern char **environ;
52 int len, i;
53 const char *np;
54 char **p, *cp;
55
56 if (name == NULL || environ == NULL)
57 return (NULL);
58 for (np = name; *np && *np != '='; ++np)
59 ;
60 len = np - name;
61 for (p = environ; (cp = *p) != NULL; ++p) {
62 for (np = name, i = len; i && *cp; i--)
63 if (*cp++ != *np++)
64 break;
65 if (i == 0 && *cp++ == '=') {
66 *offset = p - environ;
67 return (cp);
68 }
69 }
70 return (NULL);
71}
72
73/*
74 * getenv --
75 * Returns ptr to value associated with name, if any, else NULL.
76 */
77char *
78getenv(const char *name)
79{
80 int offset;
81
82 return (__findenv(name, &offset));
83}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000000..e0dc3701f9
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,372 @@
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.31 2005/03/26 22:02:15 millert Exp $
29.\"
30.Dd December 17, 2002
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.Fd #include <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.
77.Pp
78On return from
79.Fn getopt ,
80.Va optarg
81points to an option argument, if it is anticipated,
82and the variable
83.Va optind
84contains the index to the next
85.Fa argv
86argument for a subsequent call
87to
88.Fn getopt .
89.Pp
90The variables
91.Va opterr
92and
93.Va optind
94are both initialized to 1.
95The
96.Va optind
97variable may be set to another value larger than 0 before a set of calls to
98.Fn getopt
99in order to skip over more or less
100.Fa argv
101entries.
102An
103.Va optind
104value of 0 is reserved for compatibility with GNU
105.Fn getopt .
106.Pp
107In order to use
108.Fn getopt
109to evaluate multiple sets of arguments, or to evaluate a single set of
110arguments multiple times,
111the variable
112.Va optreset
113must be set to 1 before the second and each additional set of calls to
114.Fn getopt ,
115and the variable
116.Va optind
117must be reinitialized.
118.Pp
119The
120.Fn getopt
121function returns \-1 when the argument list is exhausted.
122The interpretation of options in the argument list may be cancelled
123by the option
124.Ql --
125(double dash) which causes
126.Fn getopt
127to signal the end of argument processing and return \-1.
128When all options have been processed (i.e., up to the first non-option
129argument),
130.Fn getopt
131returns \-1.
132.Sh RETURN VALUES
133The
134.Fn getopt
135function returns the next known option character in
136.Fa optstring .
137If
138.Fn getopt
139encounters a character not found in
140.Fa optstring
141or if it detects a missing option argument,
142it returns
143.Sq \&?
144(question mark).
145If
146.Fa optstring
147has a leading
148.Sq \&:
149then a missing option argument causes
150.Sq \&:
151to be returned instead of
152.Sq \&? .
153In either case, the variable
154.Va optopt
155is set to the character that caused the error.
156The
157.Fn getopt
158function returns \-1 when the argument list is exhausted.
159.Sh ENVIRONMENT
160.Bl -tag -width POSIXLY_CORRECTXX
161.It Ev POSIXLY_CORRECT
162If set, a leading
163.Sq -
164in
165.Ar optstring
166is ignored.
167.El
168.Sh EXAMPLES
169.Bd -literal -compact
170extern char *optarg;
171extern int optind;
172int bflag, ch, fd;
173
174bflag = 0;
175while ((ch = getopt(argc, argv, "bf:")) != -1) {
176 switch (ch) {
177 case 'b':
178 bflag = 1;
179 break;
180 case 'f':
181 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
182 (void)fprintf(stderr,
183 "myname: %s: %s\en", optarg, strerror(errno));
184 exit(1);
185 }
186 break;
187 case '?':
188 default:
189 usage();
190 }
191}
192argc -= optind;
193argv += optind;
194.Ed
195.Sh DIAGNOSTICS
196If the
197.Fn getopt
198function encounters a character not found in the string
199.Fa optstring
200or detects
201a missing option argument it writes an error message to
202.Em stderr
203and returns
204.Ql \&? .
205Setting
206.Va opterr
207to a zero will disable these error messages.
208If
209.Fa optstring
210has a leading
211.Ql \&:
212then a missing option argument causes a
213.Ql \&:
214to be returned in addition to suppressing any error messages.
215.Pp
216Option arguments are allowed to begin with
217.Ql - ;
218this is reasonable but reduces the amount of error checking possible.
219.Sh SEE ALSO
220.Xr getopt 1 ,
221.Xr getopt_long 3 ,
222.Xr getsubopt 3
223.Sh STANDARDS
224The
225.Fn getopt
226function implements a superset of the functionality specified by
227.St -p1003.1 .
228.Pp
229The following extensions are supported:
230.Bl -tag -width "xxx"
231.It Li o
232The
233.Va optreset
234variable was added to make it possible to call the
235.Fn getopt
236function multiple times.
237.It Li o
238If the
239.Va optind
240variable is set to 0,
241.Fn getopt
242will behave as if the
243.Va optreset
244variable has been set.
245This is for compatibility with
246.Tn GNU
247.Fn getopt .
248New code should use
249.Va optreset
250instead.
251.It Li o
252If the first character of
253.Fa optstring
254is a plus sign
255.Pq Ql + ,
256it will be ignored.
257This is for compatibility with
258.Tn GNU
259.Fn getopt .
260.It Li o
261If the first character of
262.Fa optstring
263is a dash
264.Pq Ql - ,
265non-options will be returned as arguments to the option character
266.Ql \e1 .
267This is for compatibility with
268.Tn GNU
269.Fn getopt .
270.It Li o
271A single dash
272.Pq Ql -
273may be specified as a character in
274.Fa optstring ,
275however it should
276.Em never
277have an argument associated with it.
278This allows
279.Fn getopt
280to be used with programs that expect
281.Ql -
282as an option flag.
283This practice is wrong, and should not be used in any current development.
284It is provided for backward compatibility
285.Em only .
286Care should be taken not to use
287.Ql -
288as the first character in
289.Fa optstring
290to avoid a semantic conflict with
291.Tn GNU
292.Fn getopt
293semantics (see above).
294By default, a single dash causes
295.Fn getopt
296to return \-1.
297.El
298.Pp
299Unlike
300.Tn GNU
301.Fn getopt ,
302.Ox
303does not permute the argument vector to allow non-options to be
304interspersed with options on the command line.
305Programs requiring this behavior should use
306.Xr getopt_long 3
307instead.
308Because of this (and unlike
309.Tn GNU ) ,
310the
311.Ox
312.Fn getopt
313supports optional arguments separated by whitespace.
314.Pp
315Historic
316.Bx
317versions of
318.Fn getopt
319set
320.Fa optopt
321to the last option character processed.
322However, this conflicts with
323.St -p1003.1
324which stipulates that
325.Fa optopt
326be set to the last character that caused an error.
327.Sh HISTORY
328The
329.Fn getopt
330function appeared in
331.Bx 4.3 .
332.Sh BUGS
333The
334.Fn getopt
335function was once specified to return
336.Dv EOF
337instead of \-1.
338This was changed by
339.St -p1003.2-92
340to decouple
341.Fn getopt
342from
343.Aq Pa stdio.h .
344.Pp
345It is possible to handle digits as option letters.
346This allows
347.Fn getopt
348to be used with programs that expect a number
349.Pq Dq Li \-3
350as an option.
351This practice is wrong, and should not be used in any current development.
352It is provided for backward compatibility
353.Em only .
354The following code fragment works in most cases.
355.Bd -literal -offset indent
356int ch;
357long length;
358char *p;
359
360while ((ch = getopt(argc, argv, "0123456789")) != -1) {
361 switch (ch) {
362 case '0': case '1': case '2': case '3': case '4':
363 case '5': case '6': case '7': case '8': case '9':
364 p = argv[optind - 1];
365 if (p[0] == '-' && p[1] == ch && !p[2])
366 length = ch - '0';
367 else
368 length = strtol(argv[optind] + 1, NULL, 10);
369 break;
370 }
371}
372.Ed
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..978583ef96
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,377 @@
1.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch 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 April 1, 2000
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.Fd #include <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
82myprogram --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
96The
97.Fn getopt_long
98call requires a structure to be initialized describing the long
99options.
100The structure is:
101.Bd -literal
102struct option {
103 char *name;
104 int has_arg;
105 int *flag;
106 int val;
107};
108.Ed
109.Pp
110The
111.Fa name
112field should contain the option name without the leading double dash.
113.Pp
114The
115.Fa has_arg
116field should be one of:
117.Bl -tag -width "optional_argument"
118.It Li no_argument
119no argument to the option is expect.
120.It Li required_argument
121an argument to the option is required.
122.It Li optional_argument
123an argument to the option may be presented.
124.El
125.Pp
126If
127.Fa flag
128is not
129.Dv NULL ,
130then the integer pointed to by it will be set to the value in the
131.Fa val
132field.
133If the
134.Fa flag
135field is
136.Dv NULL ,
137then the
138.Fa val
139field will be returned.
140Setting
141.Fa flag
142to
143.Dv NULL
144and setting
145.Fa val
146to the corresponding short option will make this function act just
147like
148.Xr getopt 3 .
149.Pp
150If the
151.Fa longindex
152field is not
153.Dv NULL ,
154then the integer pointed to by it will be set to the index of the long
155option relative to
156.Fa longopts .
157.Pp
158The last element of the
159.Fa longopts
160array has to be filled with zeroes.
161.Pp
162The
163.Fn getopt_long_only
164function behaves identically to
165.Fn getopt_long
166with the exception that long options may start with
167.Sq -
168in addition to
169.Sq -- .
170If an option starting with
171.Sq -
172does not match a long option but does match a single-character option,
173the single-character option is returned.
174.Sh RETURN VALUES
175If the
176.Fa flag
177field in
178.Li struct option
179is
180.Dv NULL ,
181.Fn getopt_long
182and
183.Fn getopt_long_only
184return the value specified in the
185.Fa val
186field, which is usually just the corresponding short option.
187If
188.Fa flag
189is not
190.Dv NULL ,
191these functions return 0 and store
192.Fa val
193in the location pointed to by
194.Fa flag .
195These functions return
196.Sq \:
197if there was a missing option argument,
198.Sq \&?
199if the user specified an unknown or ambiguous option, and
200\-1 when the argument list has been exhausted.
201.Sh EXAMPLES
202.Bd -literal -compact
203int bflag, ch, fd;
204int daggerset;
205
206/* options descriptor */
207static struct option longopts[] = {
208 { "buffy", no_argument, NULL, 'b' },
209 { "fluoride", required_argument, NULL, 'f' },
210 { "daggerset", no_argument, &daggerset, 1 },
211 { NULL, 0, NULL, 0 }
212};
213
214bflag = 0;
215while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
216 switch (ch) {
217 case 'b':
218 bflag = 1;
219 break;
220 case 'f':
221 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
222 err(1, "unable to open %s", optarg);
223 break;
224 case 0:
225 if (daggerset) {
226 fprintf(stderr,"Buffy will use her dagger to "
227 "apply fluoride to dracula's teeth\en");
228 }
229 break;
230 default:
231 usage();
232}
233argc -= optind;
234argv += optind;
235.Ed
236.Sh IMPLEMENTATION DIFFERENCES
237This section describes differences to the GNU implementation
238found in glibc-2.1.3:
239.Bl -tag -width "xxx"
240.It Li o
241handling of - as first char of option string in presence of
242environment variable POSIXLY_CORRECT:
243.Bl -tag -width "OpenBSD"
244.It Li GNU
245ignores POSIXLY_CORRECT and returns non-options as
246arguments to option '\e1'.
247.It Li OpenBSD
248honors POSIXLY_CORRECT and stops at the first non-option.
249.El
250.It Li o
251handling of - within the option string (not the first character):
252.Bl -tag -width "OpenBSD"
253.It Li GNU
254treats a
255.Ql -
256on the command line as a non-argument.
257.It Li OpenBSD
258a
259.Ql -
260within the option string matches a
261.Ql -
262(single dash) on the command line.
263This functionality is provided for backward compatibility with
264programs, such as
265.Xr su 1 ,
266that use
267.Ql -
268as an option flag.
269This practice is wrong, and should not be used in any current development.
270.El
271.It Li o
272handling of :: in options string in presence of POSIXLY_CORRECT:
273.Bl -tag -width "OpenBSD"
274.It Li Both
275GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
276mean the preceding option takes an optional argument.
277.El
278.It Li o
279return value in case of missing argument if first character
280(after + or -) in option string is not ':':
281.Bl -tag -width "OpenBSD"
282.It Li GNU
283returns '?'
284.It OpenBSD
285returns ':' (since OpenBSD's getopt does).
286.El
287.It Li o
288handling of --a in getopt:
289.Bl -tag -width "OpenBSD"
290.It Li GNU
291parses this as option '-', option 'a'.
292.It Li OpenBSD
293parses this as '--', and returns \-1 (ignoring the a).
294(Because the original getopt does.)
295.El
296.It Li o
297setting of optopt for long options with flag !=
298.Dv NULL :
299.Bl -tag -width "OpenBSD"
300.It Li GNU
301sets optopt to val.
302.It Li OpenBSD
303sets optopt to 0 (since val would never be returned).
304.El
305.It Li o
306handling of -W with W; in option string in getopt (not getopt_long):
307.Bl -tag -width "OpenBSD"
308.It Li GNU
309causes a segfault.
310.It Li OpenBSD
311no special handling is done;
312.Dq W;
313is interpreted as two separate options, neither of which take an argument.
314.El
315.It Li o
316setting of optarg for long options without an argument that are
317invoked via -W (W; in option string):
318.Bl -tag -width "OpenBSD"
319.It Li GNU
320sets optarg to the option name (the argument of -W).
321.It Li OpenBSD
322sets optarg to
323.Dv NULL
324(the argument of the long option).
325.El
326.It Li o
327handling of -W with an argument that is not (a prefix to) a known
328long option (W; in option string):
329.Bl -tag -width "OpenBSD"
330.It Li GNU
331returns -W with optarg set to the unknown option.
332.It Li OpenBSD
333treats this as an error (unknown option) and returns '?' with
334optopt set to 0 and optarg set to
335.Dv NULL
336(as GNU's man page documents).
337.El
338.It Li o
339The error messages are different.
340.It Li o
341OpenBSD does not permute the argument vector at the same points in
342the calling sequence as GNU does.
343The aspects normally used by the caller
344(ordering after \-1 is returned, value of optind relative
345to current positions) are the same, though.
346(We do fewer variable swaps.)
347.El
348.Sh ENVIRONMENT
349.Bl -tag -width POSIXLY_CORRECT
350.It Ev POSIXLY_CORRECT
351If set, option processing stops when the first non-option is found and
352a leading
353.Sq -
354or
355.Sq +
356in the
357.Ar optstring
358is ignored.
359.El
360.Sh SEE ALSO
361.Xr getopt 3
362.Sh HISTORY
363The
364.Fn getopt_long
365and
366.Fn getopt_long_only
367functions first appeared in GNU libiberty.
368This implementation first appeared in
369.Ox 3.3 .
370.Sh BUGS
371The
372.Ar argv
373argument is not really
374.Dv const
375as its elements may be permuted (unless
376.Ev POSIXLY_CORRECT
377is set).
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..6ddc8e2060
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,537 @@
1/* $OpenBSD: getopt_long.c,v 1.18 2005/03/30 18:51:49 pat Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3
4/*
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Sponsored in part by the Defense Advanced Research Projects
20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22 */
23/*-
24 * Copyright (c) 2000 The NetBSD Foundation, Inc.
25 * All rights reserved.
26 *
27 * This code is derived from software contributed to The NetBSD Foundation
28 * by Dieter Baron and Thomas Klausner.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the NetBSD
41 * Foundation, Inc. and its contributors.
42 * 4. Neither the name of The NetBSD Foundation nor the names of its
43 * contributors may be used to endorse or promote products derived
44 * from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
57 */
58
59#if defined(LIBC_SCCS) && !defined(lint)
60static char *rcsid = "$OpenBSD: getopt_long.c,v 1.18 2005/03/30 18:51:49 pat Exp $";
61#endif /* LIBC_SCCS and not lint */
62
63#include <err.h>
64#include <errno.h>
65#include <getopt.h>
66#include <stdlib.h>
67#include <string.h>
68
69#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
70
71#ifdef REPLACE_GETOPT
72int opterr = 1; /* if error message should be printed */
73int optind = 1; /* index into parent argv vector */
74int optopt = '?'; /* character checked for validity */
75int optreset; /* reset getopt */
76char *optarg; /* argument associated with option */
77#endif
78
79#define PRINT_ERROR ((opterr) && (*options != ':'))
80
81#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
82#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
83#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
84
85/* return values */
86#define BADCH (int)'?'
87#define BADARG ((*options == ':') ? (int)':' : (int)'?')
88#define INORDER (int)1
89
90#define EMSG ""
91
92static int getopt_internal(int, char * const *, const char *,
93 const struct option *, int *, int);
94static int parse_long_options(char * const *, const char *,
95 const struct option *, int *, int);
96static int gcd(int, int);
97static void permute_args(int, int, int, char * const *);
98
99static char *place = EMSG; /* option letter processing */
100
101/* XXX: set optreset to 1 rather than these two */
102static int nonopt_start = -1; /* first non option argument (for permute) */
103static int nonopt_end = -1; /* first option after non options (for permute) */
104
105/* Error messages */
106static const char recargchar[] = "option requires an argument -- %c";
107static const char recargstring[] = "option requires an argument -- %s";
108static const char ambig[] = "ambiguous option -- %.*s";
109static const char noarg[] = "option doesn't take an argument -- %.*s";
110static const char illoptchar[] = "unknown option -- %c";
111static const char illoptstring[] = "unknown option -- %s";
112
113/*
114 * Compute the greatest common divisor of a and b.
115 */
116static int
117gcd(int a, int b)
118{
119 int c;
120
121 c = a % b;
122 while (c != 0) {
123 a = b;
124 b = c;
125 c = a % b;
126 }
127
128 return (b);
129}
130
131/*
132 * Exchange the block from nonopt_start to nonopt_end with the block
133 * from nonopt_end to opt_end (keeping the same order of arguments
134 * in each block).
135 */
136static void
137permute_args(int panonopt_start, int panonopt_end, int opt_end,
138 char * const *nargv)
139{
140 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
141 char *swap;
142
143 /*
144 * compute lengths of blocks and number and size of cycles
145 */
146 nnonopts = panonopt_end - panonopt_start;
147 nopts = opt_end - panonopt_end;
148 ncycle = gcd(nnonopts, nopts);
149 cyclelen = (opt_end - panonopt_start) / ncycle;
150
151 for (i = 0; i < ncycle; i++) {
152 cstart = panonopt_end+i;
153 pos = cstart;
154 for (j = 0; j < cyclelen; j++) {
155 if (pos >= panonopt_end)
156 pos -= nnonopts;
157 else
158 pos += nopts;
159 swap = nargv[pos];
160 /* LINTED const cast */
161 ((char **) nargv)[pos] = nargv[cstart];
162 /* LINTED const cast */
163 ((char **)nargv)[cstart] = swap;
164 }
165 }
166}
167
168/*
169 * parse_long_options --
170 * Parse long options in argc/argv argument vector.
171 * Returns -1 if short_too is set and the option does not match long_options.
172 */
173static int
174parse_long_options(char * const *nargv, const char *options,
175 const struct option *long_options, int *idx, int short_too)
176{
177 char *current_argv, *has_equal;
178 size_t current_argv_len;
179 int i, match;
180
181 current_argv = place;
182 match = -1;
183
184 optind++;
185
186 if ((has_equal = strchr(current_argv, '=')) != NULL) {
187 /* argument found (--option=arg) */
188 current_argv_len = has_equal - current_argv;
189 has_equal++;
190 } else
191 current_argv_len = strlen(current_argv);
192
193 for (i = 0; long_options[i].name; i++) {
194 /* find matching long option */
195 if (strncmp(current_argv, long_options[i].name,
196 current_argv_len))
197 continue;
198
199 if (strlen(long_options[i].name) == current_argv_len) {
200 /* exact match */
201 match = i;
202 break;
203 }
204 /*
205 * If this is a known short option, don't allow
206 * a partial match of a single character.
207 */
208 if (short_too && current_argv_len == 1)
209 continue;
210
211 if (match == -1) /* partial match */
212 match = i;
213 else {
214 /* ambiguous abbreviation */
215 if (PRINT_ERROR)
216 warnx(ambig, (int)current_argv_len,
217 current_argv);
218 optopt = 0;
219 return (BADCH);
220 }
221 }
222 if (match != -1) { /* option found */
223 if (long_options[match].has_arg == no_argument
224 && has_equal) {
225 if (PRINT_ERROR)
226 warnx(noarg, (int)current_argv_len,
227 current_argv);
228 /*
229 * XXX: GNU sets optopt to val regardless of flag
230 */
231 if (long_options[match].flag == NULL)
232 optopt = long_options[match].val;
233 else
234 optopt = 0;
235 return (BADARG);
236 }
237 if (long_options[match].has_arg == required_argument ||
238 long_options[match].has_arg == optional_argument) {
239 if (has_equal)
240 optarg = has_equal;
241 else if (long_options[match].has_arg ==
242 required_argument) {
243 /*
244 * optional argument doesn't use next nargv
245 */
246 optarg = nargv[optind++];
247 }
248 }
249 if ((long_options[match].has_arg == required_argument)
250 && (optarg == NULL)) {
251 /*
252 * Missing argument; leading ':' indicates no error
253 * should be generated.
254 */
255 if (PRINT_ERROR)
256 warnx(recargstring,
257 current_argv);
258 /*
259 * XXX: GNU sets optopt to val regardless of flag
260 */
261 if (long_options[match].flag == NULL)
262 optopt = long_options[match].val;
263 else
264 optopt = 0;
265 --optind;
266 return (BADARG);
267 }
268 } else { /* unknown option */
269 if (short_too) {
270 --optind;
271 return (-1);
272 }
273 if (PRINT_ERROR)
274 warnx(illoptstring, current_argv);
275 optopt = 0;
276 return (BADCH);
277 }
278 if (idx)
279 *idx = match;
280 if (long_options[match].flag) {
281 *long_options[match].flag = long_options[match].val;
282 return (0);
283 } else
284 return (long_options[match].val);
285}
286
287/*
288 * getopt_internal --
289 * Parse argc/argv argument vector. Called by user level routines.
290 */
291static int
292getopt_internal(int nargc, char * const *nargv, const char *options,
293 const struct option *long_options, int *idx, int flags)
294{
295 char *oli; /* option letter list index */
296 int optchar, short_too;
297 static int posixly_correct = -1;
298
299 if (options == NULL)
300 return (-1);
301
302 /*
303 * Disable GNU extensions if POSIXLY_CORRECT is set or options
304 * string begins with a '+'.
305 */
306 if (posixly_correct == -1)
307 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
308 if (posixly_correct || *options == '+')
309 flags &= ~FLAG_PERMUTE;
310 else if (*options == '-')
311 flags |= FLAG_ALLARGS;
312 if (*options == '+' || *options == '-')
313 options++;
314
315 /*
316 * XXX Some GNU programs (like cvs) set optind to 0 instead of
317 * XXX using optreset. Work around this braindamage.
318 */
319 if (optind == 0)
320 optind = optreset = 1;
321
322 optarg = NULL;
323 if (optreset)
324 nonopt_start = nonopt_end = -1;
325start:
326 if (optreset || !*place) { /* update scanning pointer */
327 optreset = 0;
328 if (optind >= nargc) { /* end of argument vector */
329 place = EMSG;
330 if (nonopt_end != -1) {
331 /* do permutation, if we have to */
332 permute_args(nonopt_start, nonopt_end,
333 optind, nargv);
334 optind -= nonopt_end - nonopt_start;
335 }
336 else if (nonopt_start != -1) {
337 /*
338 * If we skipped non-options, set optind
339 * to the first of them.
340 */
341 optind = nonopt_start;
342 }
343 nonopt_start = nonopt_end = -1;
344 return (-1);
345 }
346 if (*(place = nargv[optind]) != '-' ||
347 (place[1] == '\0' && strchr(options, '-') == NULL)) {
348 place = EMSG; /* found non-option */
349 if (flags & FLAG_ALLARGS) {
350 /*
351 * GNU extension:
352 * return non-option as argument to option 1
353 */
354 optarg = nargv[optind++];
355 return (INORDER);
356 }
357 if (!(flags & FLAG_PERMUTE)) {
358 /*
359 * If no permutation wanted, stop parsing
360 * at first non-option.
361 */
362 return (-1);
363 }
364 /* do permutation */
365 if (nonopt_start == -1)
366 nonopt_start = optind;
367 else if (nonopt_end != -1) {
368 permute_args(nonopt_start, nonopt_end,
369 optind, nargv);
370 nonopt_start = optind -
371 (nonopt_end - nonopt_start);
372 nonopt_end = -1;
373 }
374 optind++;
375 /* process next argument */
376 goto start;
377 }
378 if (nonopt_start != -1 && nonopt_end == -1)
379 nonopt_end = optind;
380
381 /*
382 * If we have "-" do nothing, if "--" we are done.
383 */
384 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
385 optind++;
386 place = EMSG;
387 /*
388 * We found an option (--), so if we skipped
389 * non-options, we have to permute.
390 */
391 if (nonopt_end != -1) {
392 permute_args(nonopt_start, nonopt_end,
393 optind, nargv);
394 optind -= nonopt_end - nonopt_start;
395 }
396 nonopt_start = nonopt_end = -1;
397 return (-1);
398 }
399 }
400
401 /*
402 * Check long options if:
403 * 1) we were passed some
404 * 2) the arg is not just "-"
405 * 3) either the arg starts with -- we are getopt_long_only()
406 */
407 if (long_options != NULL && place != nargv[optind] &&
408 (*place == '-' || (flags & FLAG_LONGONLY))) {
409 short_too = 0;
410 if (*place == '-')
411 place++; /* --foo long option */
412 else if (*place != ':' && strchr(options, *place) != NULL)
413 short_too = 1; /* could be short option too */
414
415 optchar = parse_long_options(nargv, options, long_options,
416 idx, short_too);
417 if (optchar != -1) {
418 place = EMSG;
419 return (optchar);
420 }
421 }
422
423 if ((optchar = (int)*place++) == (int)':' ||
424 optchar == (int)'-' && *place != '\0' ||
425 (oli = strchr(options, optchar)) == NULL) {
426 /*
427 * If the user specified "-" and '-' isn't listed in
428 * options, return -1 (non-option) as per POSIX.
429 * Otherwise, it is an unknown option character (or ':').
430 */
431 if (optchar == (int)'-' && *place == '\0')
432 return (-1);
433 if (!*place)
434 ++optind;
435 if (PRINT_ERROR)
436 warnx(illoptchar, optchar);
437 optopt = optchar;
438 return (BADCH);
439 }
440 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
441 /* -W long-option */
442 if (*place) /* no space */
443 /* NOTHING */;
444 else if (++optind >= nargc) { /* no arg */
445 place = EMSG;
446 if (PRINT_ERROR)
447 warnx(recargchar, optchar);
448 optopt = optchar;
449 return (BADARG);
450 } else /* white space */
451 place = nargv[optind];
452 optchar = parse_long_options(nargv, options, long_options,
453 idx, 0);
454 place = EMSG;
455 return (optchar);
456 }
457 if (*++oli != ':') { /* doesn't take argument */
458 if (!*place)
459 ++optind;
460 } else { /* takes (optional) argument */
461 optarg = NULL;
462 if (*place) /* no white space */
463 optarg = place;
464 /* XXX: disable test for :: if PC? (GNU doesn't) */
465 else if (oli[1] != ':') { /* arg not optional */
466 if (++optind >= nargc) { /* no arg */
467 place = EMSG;
468 if (PRINT_ERROR)
469 warnx(recargchar, optchar);
470 optopt = optchar;
471 return (BADARG);
472 } else
473 optarg = nargv[optind];
474 } else if (!(flags & FLAG_PERMUTE)) {
475 /*
476 * If permutation is disabled, we can accept an
477 * optional arg separated by whitespace so long
478 * as it does not start with a dash (-).
479 */
480 if (optind + 1 < nargc && *nargv[optind + 1] != '-')
481 optarg = nargv[++optind];
482 }
483 place = EMSG;
484 ++optind;
485 }
486 /* dump back option letter */
487 return (optchar);
488}
489
490#ifdef REPLACE_GETOPT
491/*
492 * getopt --
493 * Parse argc/argv argument vector.
494 *
495 * [eventually this will replace the BSD getopt]
496 */
497int
498getopt(int nargc, char * const *nargv, const char *options)
499{
500
501 /*
502 * We dont' pass FLAG_PERMUTE to getopt_internal() since
503 * the BSD getopt(3) (unlike GNU) has never done this.
504 *
505 * Furthermore, since many privileged programs call getopt()
506 * before dropping privileges it makes sense to keep things
507 * as simple (and bug-free) as possible.
508 */
509 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
510}
511#endif /* REPLACE_GETOPT */
512
513/*
514 * getopt_long --
515 * Parse argc/argv argument vector.
516 */
517int
518getopt_long(int nargc, char * const *nargv, const char *options,
519 const struct option *long_options, int *idx)
520{
521
522 return (getopt_internal(nargc, nargv, options, long_options, idx,
523 FLAG_PERMUTE));
524}
525
526/*
527 * getopt_long_only --
528 * Parse argc/argv argument vector.
529 */
530int
531getopt_long_only(int nargc, char * const *nargv, const char *options,
532 const struct option *long_options, int *idx)
533{
534
535 return (getopt_internal(nargc, nargv, options, long_options, idx,
536 FLAG_PERMUTE|FLAG_LONGONLY));
537}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..6cb4975ced
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,143 @@
1.\" $OpenBSD: getsubopt.3,v 1.9 2005/02/25 03:12:44 cloder 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 June 9, 1993
33.Dt GETSUBOPT 3
34.Os
35.Sh NAME
36.Nm getsubopt
37.Nd get sub options from an argument
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Vt extern char *suboptarg;
41.Ft int
42.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
43.Sh DESCRIPTION
44The
45.Fn getsubopt
46function parses a string containing tokens delimited by one or more
47tab, space or comma
48.Pq Ql \&,
49characters.
50It is intended for use in parsing groups of option arguments provided
51as part of a utility command line.
52.Pp
53The argument
54.Fa optionp
55is a pointer to a pointer to the string.
56The argument
57.Fa tokens
58is a pointer to a null-terminated array of pointers to strings.
59.Pp
60The
61.Fn getsubopt
62function returns the zero-based offset of the pointer in the
63.Fa tokens
64array referencing a string which matches the first token
65in the string, or \-1 if the string contains no tokens or
66.Fa tokens
67does not contain a matching string.
68.Pp
69If the token is of the form
70.Ar name Ns = Ns Ar value ,
71the location referenced by
72.Fa valuep
73will be set to point to the start of the
74.Dq value
75portion of the token.
76.Pp
77On return from
78.Fn getsubopt ,
79.Fa optionp
80will be set to point to the start of the next token in the string,
81or the NUL at the end of the string if no more tokens are present.
82The external variable
83.Fa suboptarg
84will be set to point to the start of the current token, or
85.Dv NULL
86if no tokens were present.
87The argument
88.Fa valuep
89will be set to point to the value portion of the token, or
90.Dv NULL
91if no value portion was present.
92.Sh EXAMPLES
93.Bd -literal -compact
94char *tokens[] = {
95 #define ONE 0
96 "one",
97 #define TWO 1
98 "two",
99 NULL
100};
101
102\&...
103
104extern char *optarg, *suboptarg;
105char *options, *value;
106
107while ((ch = getopt(argc, argv, "ab:")) != \-1) {
108 switch(ch) {
109 case 'a':
110 /* process ``a'' option */
111 break;
112 case 'b':
113 options = optarg;
114 while (*options) {
115 switch(getsubopt(&options, tokens, &value)) {
116 case ONE:
117 /* process ``one'' sub option */
118 break;
119 case TWO:
120 /* process ``two'' sub option */
121 if (!value)
122 error("no value for two");
123 i = atoi(value);
124 break;
125 case \-1:
126 if (suboptarg)
127 error("illegal sub option %s",
128 suboptarg);
129 else
130 error("missing sub option");
131 break;
132 }
133 break;
134 }
135.Ed
136.Sh SEE ALSO
137.Xr getopt 3 ,
138.Xr strsep 3
139.Sh HISTORY
140The
141.Fn getsubopt
142function first appeared in
143.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/getsubopt.c b/src/lib/libc/stdlib/getsubopt.c
new file mode 100644
index 0000000000..dfd7a50bd8
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,100 @@
1/* $OpenBSD: getsubopt.c,v 1.3 2005/03/30 18:51:49 pat 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#ifndef lint
33#if 0
34static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
35#else
36static char rcsid[] = "$OpenBSD: getsubopt.c,v 1.3 2005/03/30 18:51:49 pat Exp $";
37#endif
38#endif /* not lint */
39
40#include <unistd.h>
41#include <stdlib.h>
42#include <string.h>
43
44/*
45 * The SVID interface to getsubopt provides no way of figuring out which
46 * part of the suboptions list wasn't matched. This makes error messages
47 * tricky... The extern variable suboptarg is a pointer to the token
48 * which didn't match.
49 */
50char *suboptarg;
51
52int
53getsubopt(char **optionp, char * const *tokens, char **valuep)
54{
55 int cnt;
56 char *p;
57
58 suboptarg = *valuep = NULL;
59
60 if (!optionp || !*optionp)
61 return(-1);
62
63 /* skip leading white-space, commas */
64 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
65
66 if (!*p) {
67 *optionp = p;
68 return(-1);
69 }
70
71 /* save the start of the token, and skip the rest of the token. */
72 for (suboptarg = p;
73 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
74
75 if (*p) {
76 /*
77 * If there's an equals sign, set the value pointer, and
78 * skip over the value part of the token. Terminate the
79 * token.
80 */
81 if (*p == '=') {
82 *p = '\0';
83 for (*valuep = ++p;
84 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
85 if (*p)
86 *p++ = '\0';
87 } else
88 *p++ = '\0';
89 /* Skip any whitespace or commas after this token. */
90 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
91 }
92
93 /* set optionp for next round. */
94 *optionp = p;
95
96 for (cnt = 0; *tokens; ++tokens, ++cnt)
97 if (!strcmp(suboptarg, *tokens))
98 return(cnt);
99 return(-1);
100}
diff --git a/src/lib/libc/stdlib/hcreate.3 b/src/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000000..d1d4e5c185
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,195 @@
1.\" $OpenBSD: hcreate.3,v 1.1 2004/06/24 04:43:33 millert Exp $
2.\" $NetBSD: hcreate.3,v 1.6 2003/04/16 13:34:46 wiz 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.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd February 13, 2001
39.Dt HCREATE 3
40.Os
41.Sh NAME
42.Nm hcreate ,
43.Nm hdestroy ,
44.Nm hsearch
45.Nd manage hash search table
46.Sh SYNOPSIS
47.In search.h
48.Ft int
49.Fn hcreate "size_t nel"
50.Ft void
51.Fn hdestroy "void"
52.Ft ENTRY *
53.Fn hsearch "ENTRY item" "ACTION action"
54.Sh DESCRIPTION
55The
56.Fn hcreate ,
57.Fn hdestroy
58and
59.Fn hsearch
60functions manage hash search tables.
61.Pp
62The
63.Fn hcreate
64function allocates and initializes the table.
65The
66.Fa nel
67argument specifies an estimate of the maximum number of entries to be held
68by the table.
69Unless further memory allocation fails, supplying an insufficient
70.Fa nel
71value will not result in functional harm, although a performance degradation
72may occur.
73Initialization using the
74.Fn hcreate
75function is mandatory prior to any access operations using
76.Fn hsearch .
77.Pp
78The
79.Fn hdestroy
80function destroys a table previously created using
81.Fn hcreate .
82After a call to
83.Fn hdestroy ,
84the data can no longer be accessed.
85.Pp
86The
87.Fn hsearch
88function is used to search to the hash table.
89It returns a pointer into the
90hash table indicating the address of an item.
91The
92.Fa item
93argument is of type
94.Dv ENTRY ,
95a structural type which contains the following members:
96.Bl -tag -compact -offset indent -width voidX*dataXX
97.It Fa char *key
98comparison key.
99.It Fa void *data
100pointer to data associated with
101.Fa key .
102.El
103.Pp
104The key comparison function used by
105.Fn hsearch
106is
107.Xr strcmp 3 .
108.Pp
109The
110.Fa action
111argument is of type
112.Dv ACTION ,
113an enumeration type which defines the following values:
114.Bl -tag -compact -offset indent -width ENTERXX
115.It Dv ENTER
116Insert
117.Fa item
118into the hash table.
119If an existing item with the same key is found, it is not replaced.
120Note that the
121.Fa key
122and
123.Fa data
124elements of
125.Fa item
126are used directly by the new table entry.
127The storage for the
128key must not be modified during the lifetime of the hash table.
129.It Dv FIND
130Search the hash table without inserting
131.Fa item .
132.El
133.Sh RETURN VALUES
134If successful, the
135.Fn hcreate
136function returns a non-zero value.
137Otherwise, a value of 0 is returned and
138.Va errno
139is set to indicate the error.
140.Pp
141The
142.Fn hdestroy
143functions
144returns no value.
145.Pp
146If successful, the
147.Fn hsearch
148function returns a pointer to hash table entry matching
149the provided key.
150If the action is
151.Dv FIND
152and the item was not found, or if the action is
153.Dv ENTER
154and the insertion failed,
155.Dv NULL
156is returned and
157.Va errno
158is set to indicate the error.
159If the action is
160.Dv ENTER
161and an entry already existed in the table matching the given
162key, the existing entry is returned and is not replaced.
163.Sh ERRORS
164The
165.Fn hcreate
166and
167.Fn hsearch
168functions will fail if:
169.Bl -tag -width Er
170.It Bq Er ENOMEM
171Insufficient memory is available.
172.El
173.Sh SEE ALSO
174.Xr bsearch 3 ,
175.Xr lsearch 3 ,
176.Xr malloc 3 ,
177.Xr strcmp 3
178.Sh STANDARDS
179The
180.Fn hcreate ,
181.Fn hdestroy
182and
183.Fn hsearch
184functions conform to
185.St -xpg4.2 .
186.Sh HISTORY
187The
188.Fn hcreate ,
189.Fn hdestroy
190and
191.Fn hsearch
192functions first appeared in
193.At V .
194.Sh BUGS
195The interface permits the use of only one hash table at a time.
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000000..14e6fa41f2
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,200 @@
1/* $OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert 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#ifndef lint
51static const char copyright[] =
52"@(#) Copyright (c) 2001 Christopher G. Demetriou. All rights reserved.\n";
53#endif /* not lint */
54
55#ifndef lint
56static const char rcsid[] = "$OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert Exp $";
57#endif /* not lint */
58
59#include "namespace.h"
60#include <assert.h>
61#include <errno.h>
62#include <inttypes.h>
63#include <search.h>
64#include <stdlib.h>
65#include <string.h>
66#include <sys/queue.h>
67
68#ifndef _DIAGASSERT
69#define _DIAGASSERT
70#endif
71
72/*
73 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
74 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
75 */
76struct internal_entry {
77 SLIST_ENTRY(internal_entry) link;
78 ENTRY ent;
79};
80SLIST_HEAD(internal_head, internal_entry);
81
82#define MIN_BUCKETS_LG2 4
83#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
84
85/*
86 * max * sizeof internal_entry must fit into size_t.
87 * assumes internal_entry is <= 32 (2^5) bytes.
88 */
89#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
90#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
91
92/* Default hash function, from db/hash/hash_func.c */
93extern u_int32_t (*__default_hash)(const void *, size_t);
94
95static struct internal_head *htable;
96static size_t htablesize;
97
98int
99hcreate(size_t nel)
100{
101 size_t idx;
102 unsigned int p2;
103
104 /* Make sure this isn't called when a table already exists. */
105 _DIAGASSERT(htable == NULL);
106 if (htable != NULL) {
107 errno = EINVAL;
108 return 0;
109 }
110
111 /* If nel is too small, make it min sized. */
112 if (nel < MIN_BUCKETS)
113 nel = MIN_BUCKETS;
114
115 /* If it's too large, cap it. */
116 if (nel > MAX_BUCKETS)
117 nel = MAX_BUCKETS;
118
119 /* If it's is not a power of two in size, round up. */
120 if ((nel & (nel - 1)) != 0) {
121 for (p2 = 0; nel != 0; p2++)
122 nel >>= 1;
123 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
124 nel = 1 << p2;
125 }
126
127 /* Allocate the table. */
128 htablesize = nel;
129 htable = malloc(htablesize * sizeof htable[0]);
130 if (htable == NULL) {
131 errno = ENOMEM;
132 return 0;
133 }
134
135 /* Initialize it. */
136 for (idx = 0; idx < htablesize; idx++)
137 SLIST_INIT(&htable[idx]);
138
139 return 1;
140}
141
142void
143hdestroy(void)
144{
145 struct internal_entry *ie;
146 size_t idx;
147
148 _DIAGASSERT(htable != NULL);
149 if (htable == NULL)
150 return;
151
152 for (idx = 0; idx < htablesize; idx++) {
153 while (!SLIST_EMPTY(&htable[idx])) {
154 ie = SLIST_FIRST(&htable[idx]);
155 SLIST_REMOVE_HEAD(&htable[idx], link);
156 free(ie->ent.key);
157 free(ie);
158 }
159 }
160 free(htable);
161 htable = NULL;
162}
163
164ENTRY *
165hsearch(ENTRY item, ACTION action)
166{
167 struct internal_head *head;
168 struct internal_entry *ie;
169 uint32_t hashval;
170 size_t len;
171
172 _DIAGASSERT(htable != NULL);
173 _DIAGASSERT(item.key != NULL);
174 _DIAGASSERT(action == ENTER || action == FIND);
175
176 len = strlen(item.key);
177 hashval = (*__default_hash)(item.key, len);
178
179 head = &htable[hashval & (htablesize - 1)];
180 ie = SLIST_FIRST(head);
181 while (ie != NULL) {
182 if (strcmp(ie->ent.key, item.key) == 0)
183 break;
184 ie = SLIST_NEXT(ie, link);
185 }
186
187 if (ie != NULL)
188 return &ie->ent;
189 else if (action == FIND)
190 return NULL;
191
192 ie = malloc(sizeof *ie);
193 if (ie == NULL)
194 return NULL;
195 ie->ent.key = item.key;
196 ie->ent.data = item.data;
197
198 SLIST_INSERT_HEAD(head, ie, link);
199 return &ie->ent;
200}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000000..dcc0c8baad
--- /dev/null
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,177 @@
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: heapsort.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/types.h>
38#include <errno.h>
39#include <stdlib.h>
40
41/*
42 * Swap two areas of size number of bytes. Although qsort(3) permits random
43 * blocks of memory to be sorted, sorting pointers is almost certainly the
44 * common case (and, were it not, could easily be made so). Regardless, it
45 * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
46 * arithmetic gets lost in the time required for comparison function calls.
47 */
48#define SWAP(a, b, count, size, tmp) { \
49 count = size; \
50 do { \
51 tmp = *a; \
52 *a++ = *b; \
53 *b++ = tmp; \
54 } while (--count); \
55}
56
57/* Copy one block of size size to another. */
58#define COPY(a, b, count, size, tmp1, tmp2) { \
59 count = size; \
60 tmp1 = a; \
61 tmp2 = b; \
62 do { \
63 *tmp1++ = *tmp2++; \
64 } while (--count); \
65}
66
67/*
68 * Build the list into a heap, where a heap is defined such that for
69 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
70 *
71 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
72 * j < nmemb, select largest of Ki, Kj and Kj+1.
73 */
74#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
75 for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
76 par_i = child_i) { \
77 child = base + child_i * size; \
78 if (child_i < nmemb && compar(child, child + size) < 0) { \
79 child += size; \
80 ++child_i; \
81 } \
82 par = base + par_i * size; \
83 if (compar(child, par) <= 0) \
84 break; \
85 SWAP(par, child, count, size, tmp); \
86 } \
87}
88
89/*
90 * Select the top of the heap and 'heapify'. Since by far the most expensive
91 * action is the call to the compar function, a considerable optimization
92 * in the average case can be achieved due to the fact that k, the displaced
93 * element, is usually quite small, so it would be preferable to first
94 * heapify, always maintaining the invariant that the larger child is copied
95 * over its parent's record.
96 *
97 * Then, starting from the *bottom* of the heap, finding k's correct place,
98 * again maintaining the invariant. As a result of the invariant no element
99 * is 'lost' when k is assigned its correct place in the heap.
100 *
101 * The time savings from this optimization are on the order of 15-20% for the
102 * average case. See Knuth, Vol. 3, page 158, problem 18.
103 *
104 * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
105 */
106#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
107 for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
108 child = base + child_i * size; \
109 if (child_i < nmemb && compar(child, child + size) < 0) { \
110 child += size; \
111 ++child_i; \
112 } \
113 par = base + par_i * size; \
114 COPY(par, child, count, size, tmp1, tmp2); \
115 } \
116 for (;;) { \
117 child_i = par_i; \
118 par_i = child_i / 2; \
119 child = base + child_i * size; \
120 par = base + par_i * size; \
121 if (child_i == 1 || compar(k, par) < 0) { \
122 COPY(child, k, count, size, tmp1, tmp2); \
123 break; \
124 } \
125 COPY(child, par, count, size, tmp1, tmp2); \
126 } \
127}
128
129/*
130 * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
131 * and worst. While heapsort is faster than the worst case of quicksort,
132 * the BSD quicksort does median selection so that the chance of finding
133 * a data set that will trigger the worst case is nonexistent. Heapsort's
134 * only advantage over quicksort is that it requires little additional memory.
135 */
136int
137heapsort(void *vbase, size_t nmemb, size_t size,
138 int (*compar)(const void *, const void *))
139{
140 int cnt, i, j, l;
141 char tmp, *tmp1, *tmp2;
142 char *base, *k, *p, *t;
143
144 if (nmemb <= 1)
145 return (0);
146
147 if (!size) {
148 errno = EINVAL;
149 return (-1);
150 }
151
152 if ((k = malloc(size)) == NULL)
153 return (-1);
154
155 /*
156 * Items are numbered from 1 to nmemb, so offset from size bytes
157 * below the starting address.
158 */
159 base = (char *)vbase - size;
160
161 for (l = nmemb / 2 + 1; --l;)
162 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
163
164 /*
165 * For each element of the heap, save the largest element into its
166 * final slot, save the displaced element (k), then recreate the
167 * heap.
168 */
169 while (nmemb > 1) {
170 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
171 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
172 --nmemb;
173 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
174 }
175 free(k);
176 return (0);
177}
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..cd8110ed90
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.3 2004/01/25 14:48:32 jmc Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd August 12, 1993
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.Fd #include <search.h>
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superceded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Sh DIAGNOSTICS
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn lsearch
87and
88.Fn lfind
89functions conform to the
90.St -p1003.1-2001
91and
92.St -xpg4.3 .
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the insque and remque instructions on a
100.Tn VAX .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..549246c71f
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43insque(void *entry, void *pred)
44{
45 struct qelem *e = (struct qelem *) entry;
46 struct qelem *p = (struct qelem *) pred;
47
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 p->q_forw->q_back = e;
51 p->q_forw = e;
52}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
new file mode 100644
index 0000000000..99cddb71e5
--- /dev/null
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -0,0 +1,25 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: jrand48.c,v 1.2 1996/08/19 08:33:33 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20long
21jrand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ((long) xseed[2] << 16) + (long) xseed[1];
25}
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000000..325b41b33b
--- /dev/null
+++ b/src/lib/libc/stdlib/l64a.c
@@ -0,0 +1,45 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: l64a.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13char *
14l64a(long value)
15{
16 static char buf[8];
17 char *s = buf;
18 int digit;
19 int i;
20
21 if (value < 0) {
22 errno = EINVAL;
23 return(NULL);
24 }
25
26 for (i = 0; value != 0 && i < 6; i++) {
27 digit = value & 0x3f;
28
29 if (digit < 2)
30 *s = digit + '.';
31 else if (digit < 12)
32 *s = digit + '0' - 2;
33 else if (digit < 38)
34 *s = digit + 'A' - 12;
35 else
36 *s = digit + 'a' - 38;
37
38 value >>= 6;
39 s++;
40 }
41
42 *s = '\0';
43
44 return(buf);
45}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
new file mode 100644
index 0000000000..742f3eedba
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.3
@@ -0,0 +1,68 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: labs.3,v 1.7 2003/07/21 20:20:04 millert Exp $
33.\"
34.Dd May 14, 2003
35.Dt LABS 3
36.Os
37.Sh NAME
38.Nm labs, llabs
39.Nd return the absolute value of a long integer
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft long
43.Fn labs "long i"
44.Ft long long
45.Fn llabs "long long j"
46.Sh DESCRIPTION
47The
48.Fn labs
49function returns the absolute value of the long integer
50.Fa i .
51The
52.Fn llabs
53function returns the absolute value of the long long integer
54.Fa j .
55.Sh SEE ALSO
56.Xr abs 3 ,
57.Xr cabs 3 ,
58.Xr floor 3 ,
59.Xr math 3
60.Sh STANDARDS
61The
62.Fn labs
63and
64.Fn llabs
65functions conform to
66.St -ansiC-99 .
67.Sh BUGS
68The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
new file mode 100644
index 0000000000..1dc8b0184a
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: labs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37labs(long j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
new file mode 100644
index 0000000000..44bd74e48a
--- /dev/null
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -0,0 +1,34 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lcong48.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24void
25lcong48(unsigned short p[7])
26{
27 __rand48_seed[0] = p[0];
28 __rand48_seed[1] = p[1];
29 __rand48_seed[2] = p[2];
30 __rand48_mult[0] = p[3];
31 __rand48_mult[1] = p[4];
32 __rand48_mult[2] = p[5];
33 __rand48_add = p[6];
34}
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
new file mode 100644
index 0000000000..63e1f2165c
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" 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.7 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt LDIV 3
36.Os
37.Sh NAME
38.Nm ldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft ldiv_t
43.Fn ldiv "long num" "long denom"
44.Sh DESCRIPTION
45The
46.Fn ldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li ldiv_t
51that contains two
52.Li long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr math 3 ,
60.Xr qdiv 3
61.Sh STANDARDS
62The
63.Fn ldiv
64function conforms to
65.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000000..bbb539a68b
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: ldiv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* ldiv_t */
38
39ldiv_t
40ldiv(long num, long denom)
41{
42 ldiv_t r;
43
44 /* see div.c for comments */
45
46 r.quot = num / denom;
47 r.rem = num % denom;
48 if (num >= 0 && r.rem < 0) {
49 r.quot++;
50 r.rem -= denom;
51 }
52 return (r);
53}
diff --git a/src/lib/libc/stdlib/llabs.c b/src/lib/libc/stdlib/llabs.c
new file mode 100644
index 0000000000..9611b5aefd
--- /dev/null
+++ b/src/lib/libc/stdlib/llabs.c
@@ -0,0 +1,45 @@
1/* $OpenBSD: llabs.c,v 1.1 2003/07/21 20:20:04 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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: llabs.c,v 1.1 2003/07/21 20:20:04 millert Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <stdlib.h>
41
42long long llabs(long long j)
43{
44 return (j < 0 ? -j : j);
45}
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
new file mode 100644
index 0000000000..6b7524a51b
--- /dev/null
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -0,0 +1,27 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lrand48.c,v 1.2 1996/08/19 08:33:36 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22long
23lrand48(void)
24{
25 __dorand48(__rand48_seed);
26 return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1);
27}
diff --git a/src/lib/libc/stdlib/lsearch.3 b/src/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000000..818aa1bb43
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,105 @@
1.\" $OpenBSD: lsearch.3,v 1.4 2004/10/01 04:08:45 jsg 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 June 4, 1993
33.Dt LSEARCH 3
34.Os
35.Sh NAME
36.Nm lsearch ,
37.Nm lfind
38.Nd linear searching routines
39.Sh SYNOPSIS
40.Ft char *
41.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
42.Ft char *
43.Fn lfind "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
44.Sh DESCRIPTION
45The functions
46.Fn lsearch ,
47and
48.Fn lfind
49provide basic linear searching functionality.
50.Pp
51.Fa base
52is the pointer to the beginning of an array.
53The argument
54.Fa nelp
55is the current number of elements in the array, where each element
56is
57.Fa width
58bytes long.
59The
60.Fa compar
61function
62is a comparison routine which is used to compare two elements.
63It takes two arguments which point to the
64.Fa key
65object and to an array member, in that order, and must return an integer
66less than, equivalent to, or greater than zero if the
67.Fa key
68object is considered, respectively, to be less than, equal to, or greater
69than the array member.
70.Pp
71The
72.Fn lsearch
73and
74.Fn lfind
75functions
76return a pointer into the array referenced by
77.Fa base
78where
79.Fa key
80is located.
81If
82.Fa key
83does not exist,
84.Fn lfind
85will return a null pointer and
86.Fn lsearch
87will add it to the array.
88When an element is added to the array by
89.Fn lsearch
90the location referenced by the argument
91.Fa nelp
92is incremented by one.
93.Sh SEE ALSO
94.Xr bsearch 3 ,
95.Xr db 3
96.Sh STANDARDS
97The
98.Fn lsearch
99and
100.Fn lfind
101functions conform to the
102.St -p1003.1-2001
103and
104.St -xpg4.3 .
105specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..0815430199
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,88 @@
1/* $OpenBSD: lsearch.c,v 1.3 2004/10/01 04:08:45 jsg 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#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h>
40#include <string.h>
41#include <search.h>
42
43typedef int (*cmp_fn_t)(const void *, const void *);
44static void *linear_base(const void *, const void *, size_t *, size_t,
45 cmp_fn_t, int);
46
47void *
48lsearch(const void *key, const void *base, size_t *nelp, size_t width,
49 cmp_fn_t compar)
50{
51
52 return(linear_base(key, base, nelp, width, compar, 1));
53}
54
55void *
56lfind(const void *key, const void *base, size_t *nelp, size_t width,
57 cmp_fn_t compar)
58{
59 return(linear_base(key, base, nelp, width, compar, 0));
60}
61
62static void *
63linear_base(const void *key, const void *base, size_t *nelp, size_t width,
64 cmp_fn_t compar, int add_flag)
65{
66 const char *element, *end;
67
68 end = (const char *)base + *nelp * width;
69 for (element = base; element < end; element += width)
70 if (!compar(key, element)) /* key found */
71 return((void *)element);
72
73 if (!add_flag) /* key not found */
74 return(NULL);
75
76 /*
77 * The UNIX System User's Manual, 1986 edition claims that
78 * a NULL pointer is returned by lsearch with errno set
79 * appropriately, if there is not enough room in the table
80 * to add a new item. This can't be done as none of these
81 * routines have any method of determining the size of the
82 * table. This comment isn't in the 1986-87 System V
83 * manual.
84 */
85 ++*nelp;
86 memcpy((void *)end, key, width);
87 return((void *)end);
88}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
new file mode 100644
index 0000000000..138ec708e8
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,431 @@
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.37 2004/07/02 10:42:55 jmc Exp $
34.\"
35.Dd August 27, 1996
36.Dt MALLOC 3
37.Os
38.Sh NAME
39.Nm malloc ,
40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm cfree
44.Nd memory allocation and deallocation
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void *
48.Fn malloc "size_t size"
49.Ft void *
50.Fn calloc "size_t nmemb" "size_t size"
51.Ft void *
52.Fn realloc "void *ptr" "size_t size"
53.Ft void
54.Fn free "void *ptr"
55.Ft void
56.Fn cfree "void *ptr"
57.Ft char *
58.Va malloc_options ;
59.Sh DESCRIPTION
60The
61.Fn malloc
62function allocates uninitialized space for an object whose
63size is specified by
64.Fa size .
65The
66.Fn malloc
67function maintains multiple lists of free blocks according to size, allocating
68space from the appropriate list.
69.Pp
70The allocated space is
71suitably aligned (after possible pointer
72coercion) for storage of any type of object.
73If the space is of
74.Em pagesize
75or larger, the memory returned will be page-aligned.
76.Pp
77Allocation of a zero size object returns a pointer to a zero size object.
78This zero size object is access protected, so any access to it will
79generate an exception (SIGSEGV).
80Many zero-sized objects can be placed consecutively in shared
81protected pages.
82The minimum size of the protection on each object is suitably aligned and
83sized as previously stated, but the protection may extend further depending
84on where in a protected zone the object lands.
85.Pp
86The
87.Fn calloc
88function allocates space for an array of
89.Fa nmemb
90objects, each of whose size is
91.Fa size .
92The space is initialized to all bits zero.
93.Pp
94The
95.Fn free
96function causes the space pointed to by
97.Fa ptr
98to be deallocated, that is, at least made available for further allocation,
99but if possible, it will passed back to the kernel with
100.Xr sbrk 2 .
101If
102.Fa ptr
103is a null pointer, no action occurs.
104.Pp
105A
106.Fn cfree
107function is also provided for compatibility with old systems and other
108.Nm malloc
109libraries; it is simply an alias for
110.Fn free .
111.Pp
112The
113.Fn realloc
114function changes the size of the object pointed to by
115.Fa ptr
116to
117.Fa size
118bytes and returns a pointer to the (possibly moved) object.
119The contents of the object are unchanged up to the lesser
120of the new and old sizes.
121If the new size is larger, the value of the newly allocated portion
122of the object is indeterminate and uninitialized.
123If
124.Fa ptr
125is a null pointer, the
126.Fn realloc
127function behaves like the
128.Fn malloc
129function for the specified size.
130If the space cannot be allocated, the object
131pointed to by
132.Fa ptr
133is unchanged.
134If
135.Fa size
136is zero and
137.Fa ptr
138is not a null pointer, the object it points to is freed and a new zero size
139object is returned.
140.Pp
141When using
142.Fn realloc
143one must be careful to avoid the following idiom:
144.Bd -literal -offset indent
145size += 50;
146if ((p = realloc(p, size)) == NULL)
147 return (NULL);
148.Ed
149.Pp
150Do not adjust the variable describing how much memory has been allocated
151until one knows the allocation has been successful.
152This can cause aberrant program behavior if the incorrect size value is used.
153In most cases, the above sample will also result in a leak of memory.
154As stated earlier, a return value of
155.Dv NULL
156indicates that the old object still remains allocated.
157Better code looks like this:
158.Bd -literal -offset indent
159newsize = size + 50;
160if ((newp = realloc(p, newsize)) == NULL) {
161 free(p);
162 p = NULL;
163 size = 0;
164 return (NULL);
165}
166p = newp;
167size = newsize;
168.Ed
169.Pp
170Malloc will first look for a symbolic link called
171.Pa /etc/malloc.conf
172and next check the environment for a variable called
173.Ev MALLOC_OPTIONS
174and finally for the global variable
175.Va malloc_options
176and scan them for flags in that order.
177Flags are single letters, uppercase means on, lowercase means off.
178.Bl -tag -width indent
179.It Cm A
180.Dq Abort .
181.Fn malloc
182will coredump the process, rather than tolerate failure.
183This is a very handy debugging aid, since the core file will represent the
184time of failure, rather than when the null pointer was accessed.
185.Pp
186.It Cm D
187.Dq Dump .
188.Fn malloc
189will dump statistics in a file called
190.Pa malloc.out
191at exit.
192This option requires the library to have been compiled with -DMALLOC_STATS in
193order to have any effect.
194.Pp
195.It Cm F
196.Dq Freeguard .
197Enable use after free protection.
198Unused pages on the freelist are read and write protected to
199cause a segmentation fault upon access.
200.Pp
201.It Cm G
202.Dq Guard .
203Enable guard pages and chunk randomization.
204Each page size or larger allocation is followed by a guard page that will
205cause a segmentation fault upon any access.
206Smaller than page size chunks are returned in a random order.
207.Pp
208.It Cm H
209.Dq Hint .
210Pass a hint to the kernel about pages we don't use.
211If the machine is paging a lot this may help a bit.
212.Pp
213.It Cm J
214.Dq Junk .
215Fill some junk into the area allocated.
216Currently junk is bytes of 0xd0; this is pronounced
217.Dq Duh .
218\&:-)
219.Pp
220.It Cm N
221Do not output warning messages when encountering possible corruption
222or bad pointers.
223.Pp
224.It Cm R
225.Dq realloc .
226Always reallocate when
227.Fn realloc
228is called, even if the initial allocation was big enough.
229This can substantially aid in compacting memory.
230.\".Pp
231.\".It Cm U
232.\".Dq utrace .
233.\"Generate entries for
234.\".Xr ktrace 1
235.\"for all operations.
236.\"Consult the source for this one.
237.Pp
238.It Cm X
239.Dq xmalloc .
240Rather than return failure,
241.Xr abort 3
242the program with a diagnostic message on stderr.
243It is the intention that this option be set at compile time by
244including in the source:
245.Bd -literal -offset indent
246extern char *malloc_options;
247malloc_options = "X";
248.Ed
249.Pp
250.It Cm Z
251.Dq Zero .
252Fill some junk into the area allocated (see
253.Cm J ) ,
254except for the exact length the user asked for, which is zeroed.
255.Pp
256.It Cm <
257.Dq Half the cache size .
258Reduce the size of the cache by a factor of two.
259.Pp
260.It Cm >
261.Dq Double the cache size .
262Double the size of the cache by a factor of two.
263.El
264.Pp
265So to set a systemwide reduction of cache size and coredumps on problems
266one would:
267.Li ln -s 'A<' /etc/malloc.conf
268.Pp
269The
270.Cm J
271and
272.Cm Z
273flags are mostly for testing and debugging.
274If a program changes behavior if either of these options are used,
275it is buggy.
276.Pp
277The default cache size is 16 pages.
278.Sh RETURN VALUES
279The
280.Fn malloc
281and
282.Fn calloc
283functions return a pointer to the allocated space if successful; otherwise,
284a null pointer is returned and
285.Va errno
286is set to
287.Er ENOMEM .
288.Pp
289The
290.Fn free
291and
292.Fn cfree
293functions return no value.
294.Pp
295The
296.Fn realloc
297function returns a pointer to the (possibly moved) allocated space
298if successful; otherwise, a null pointer is returned and
299.Va errno
300is set to
301.Er ENOMEM .
302.Sh ENVIRONMENT
303See above.
304.Sh FILES
305.Bl -tag -width "/etc/malloc.conf"
306.It Pa /etc/malloc.conf
307symbolic link to filename containing option flags
308.El
309.Sh DIAGNOSTICS
310If
311.Fn malloc ,
312.Fn calloc ,
313.Fn realloc ,
314or
315.Fn free
316detect an error or warning condition,
317a message will be printed to file descriptor
3182 (not using stdio).
319Errors will always result in the process being
320.Xr abort 3 'ed.
321If the
322.Cm A
323option has been specified, warnings will also
324.Xr abort 3
325the process.
326.Pp
327Here is a brief description of the error messages and what they mean:
328.Bl -tag -width Fl
329.It Dq (ES): mumble mumble mumble
330.Fn malloc
331has been compiled with
332.Dv \&-DEXTRA_SANITY
333and something looks fishy in there.
334Consult sources and/or wizards.
335.It Dq allocation failed
336If the
337.Cm A
338option is specified it is an error for
339.Fn malloc ,
340.Fn calloc ,
341or
342.Fn realloc
343to return
344.Dv NULL .
345.It Dq mmap(2) failed, check limits.
346This is a rather weird condition that is most likely to indicate a
347seriously overloaded system or a
348.Xr ulimit 1
349restriction.
350.It Dq freelist is destroyed.
351.Fn malloc Ns 's
352internal freelist has been stomped on.
353.El
354.Pp
355Here is a brief description of the warning messages and what they mean:
356.Bl -tag -width Fl
357.It Dq chunk/page is already free.
358There was an attempt to free a chunk that had already been freed.
359.It Dq junk pointer, too high to make sense.
360The pointer doesn't make sense.
361It's above the area of memory that
362.Fn malloc
363knows something about.
364This could be a pointer from some
365.Xr mmap 2 'ed
366memory.
367.It Dq junk pointer, too low to make sense.
368The pointer doesn't make sense.
369It's below the area of memory that
370.Fn malloc
371knows something about.
372This pointer probably came from your data or bss segments.
373.It Dq malloc() has never been called.
374Nothing has ever been allocated, yet something is being freed or
375realloc'ed.
376.It Dq modified (chunk-/page-) pointer.
377The pointer passed to free or realloc has been modified.
378.It Dq pointer to wrong page.
379The pointer that
380.Fn malloc
381is trying to free is not pointing to
382a sensible page.
383.It Dq recursive call.
384An attempt was made to call recursively into these functions, i.e., from a
385signal handler.
386This behavior is not supported.
387In particular, signal handlers should
388.Em not
389use any of the
390.Fn malloc
391functions nor utilize any other functions which may call
392.Fn malloc
393(e.g.,
394.Xr stdio 3
395routines).
396.It Dq unknown char in MALLOC_OPTIONS
397We found something we didn't understand.
398.El
399.Sh SEE ALSO
400.Xr brk 2 ,
401.Xr alloca 3 ,
402.Xr getpagesize 3
403.Sh STANDARDS
404The
405.Fn malloc
406function conforms to
407.St -ansiC .
408.Sh HISTORY
409The present implementation of
410.Fn malloc
411started out as a filesystem on a drum
412attached to a 20-bit binary challenged computer built with discrete germanium
413transistors, and it has since graduated to handle primary storage rather than
414secondary.
415.Pp
416The main difference from other
417.Fn malloc
418implementations are believed to be that
419the free pages are not accessed until allocated.
420Most
421.Fn malloc
422implementations will store a data structure containing a,
423possibly double-, linked list in the free chunks of memory, used to tie
424all the free memory together.
425That is a quite suboptimal thing to do.
426Every time the free-list is traversed, all the otherwise unused, and very
427likely paged out, pages get faulted into primary memory, just to see what
428lies after them in the list.
429.Pp
430On systems which are paging, this can increase the page-faults
431of a process by a factor of five.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000000..ae89f5d72b
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1698 @@
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 */
9
10#if defined(LIBC_SCCS) && !defined(lint)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.72 2005/03/31 21:24:46 tdeval Exp $";
12#endif /* LIBC_SCCS and not lint */
13
14/*
15 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
16 * related to internal conditions and consistency in malloc.c. This has
17 * a noticeable runtime performance hit, and generally will not do you
18 * any good unless you fiddle with the internals of malloc or want
19 * to catch random pointer corruption as early as possible.
20 */
21#ifndef MALLOC_EXTRA_SANITY
22#undef MALLOC_EXTRA_SANITY
23#endif
24
25/*
26 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
27 * the [dD] options in the MALLOC_OPTIONS environment variable.
28 * It has no run-time performance hit, but does pull in stdio...
29 */
30#ifndef MALLOC_STATS
31#undef MALLOC_STATS
32#endif
33
34/*
35 * What to use for Junk. This is the byte value we use to fill with
36 * when the 'J' option is enabled.
37 */
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
39
40#include <sys/types.h>
41#include <sys/time.h>
42#include <sys/resource.h>
43#include <sys/param.h>
44#include <sys/mman.h>
45#include <sys/uio.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50#include <fcntl.h>
51#include <limits.h>
52#include <errno.h>
53
54#include "thread_private.h"
55
56/*
57 * The basic parameters you can tweak.
58 *
59 * malloc_pageshift pagesize = 1 << malloc_pageshift
60 * It's probably best if this is the native
61 * page size, but it shouldn't have to be.
62 *
63 * malloc_minsize minimum size of an allocation in bytes.
64 * If this is too small it's too much work
65 * to manage them. This is also the smallest
66 * unit of alignment used for the storage
67 * returned by malloc/realloc.
68 *
69 */
70
71#if defined(__OpenBSD__) && defined(__sparc__)
72# define malloc_pageshift 13U
73#endif /* __OpenBSD__ */
74
75/*
76 * No user serviceable parts behind this point.
77 *
78 * This structure describes a page worth of chunks.
79 */
80
81struct pginfo {
82 struct pginfo *next; /* next on the free list */
83 void *page; /* Pointer to the page */
84 u_short size; /* size of this page's chunks */
85 u_short shift; /* How far to shift for this size chunks */
86 u_short free; /* How many free chunks */
87 u_short total; /* How many chunk */
88 u_long bits[1]; /* Which chunks are free */
89};
90
91/*
92 * This structure describes a number of free pages.
93 */
94
95struct pgfree {
96 struct pgfree *next; /* next run of free pages */
97 struct pgfree *prev; /* prev run of free pages */
98 void *page; /* pointer to free pages */
99 void *pdir; /* pointer to the base page's dir */
100 size_t size; /* number of bytes free */
101};
102
103/*
104 * How many bits per u_long in the bitmap.
105 * Change only if not 8 bits/byte
106 */
107#define MALLOC_BITS (8*sizeof(u_long))
108
109/*
110 * Magic values to put in the page_directory
111 */
112#define MALLOC_NOT_MINE ((struct pginfo*) 0)
113#define MALLOC_FREE ((struct pginfo*) 1)
114#define MALLOC_FIRST ((struct pginfo*) 2)
115#define MALLOC_FOLLOW ((struct pginfo*) 3)
116#define MALLOC_MAGIC ((struct pginfo*) 4)
117
118#ifndef malloc_pageshift
119#define malloc_pageshift (PGSHIFT)
120#endif
121
122#ifndef malloc_minsize
123#define malloc_minsize 16U
124#endif
125
126#ifndef malloc_pageshift
127#error "malloc_pageshift undefined"
128#endif
129
130#if !defined(malloc_pagesize)
131#define malloc_pagesize (1UL<<malloc_pageshift)
132#endif
133
134#if ((1UL<<malloc_pageshift) != malloc_pagesize)
135#error "(1UL<<malloc_pageshift) != malloc_pagesize"
136#endif
137
138#ifndef malloc_maxsize
139#define malloc_maxsize ((malloc_pagesize)>>1)
140#endif
141
142/* A mask for the offset inside a page. */
143#define malloc_pagemask ((malloc_pagesize)-1)
144
145#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
146#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
147
148/* fd of /dev/zero */
149#ifdef USE_DEV_ZERO
150static int fdzero;
151#define MMAP_FD fdzero
152#define INIT_MMAP() \
153 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
154 wrterror("open of /dev/zero\n"); }
155#else
156#define MMAP_FD (-1)
157#define INIT_MMAP()
158#endif
159
160/* Set when initialization has been done */
161static unsigned int malloc_started;
162
163/* Number of free pages we cache */
164static unsigned int malloc_cache = 16;
165
166/* Structure used for linking discrete directory pages. */
167struct pdinfo {
168 struct pginfo **base;
169 struct pdinfo *prev;
170 struct pdinfo *next;
171 u_long dirnum;
172};
173static struct pdinfo *last_dir; /* Caches to the last and previous */
174static struct pdinfo *prev_dir; /* referenced directory pages. */
175
176static size_t pdi_off;
177static u_long pdi_mod;
178#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
179#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
180#define PI_IDX(index) ((index) / pdi_mod)
181#define PI_OFF(index) ((index) % pdi_mod)
182
183/* The last index in the page directory we care about */
184static u_long last_index;
185
186/* Pointer to page directory. Allocated "as if with" malloc */
187static struct pginfo **page_dir;
188
189/* Free pages line up here */
190static struct pgfree free_list;
191
192/* Abort(), user doesn't handle problems. */
193static int malloc_abort = 2;
194
195/* Are we trying to die ? */
196static int suicide;
197
198#ifdef MALLOC_STATS
199/* dump statistics */
200static int malloc_stats;
201#endif
202
203/* avoid outputting warnings? */
204static int malloc_silent;
205
206/* always realloc ? */
207static int malloc_realloc;
208
209/* mprotect free pages PROT_NONE? */
210static int malloc_freeprot;
211
212/* use guard pages after allocations? */
213static int malloc_guard = 0;
214
215#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
216/* pass the kernel a hint on free pages ? */
217static int malloc_hint;
218#endif
219
220/* xmalloc behaviour ? */
221static int malloc_xmalloc;
222
223/* zero fill ? */
224static int malloc_zero;
225
226/* junk fill ? */
227static int malloc_junk;
228
229#ifdef __FreeBSD__
230/* utrace ? */
231static int malloc_utrace;
232
233struct ut { void *p; size_t s; void *r; };
234
235void utrace(struct ut *, int);
236
237#define UTRACE(a, b, c) \
238 if (malloc_utrace) \
239 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
240#else /* !__FreeBSD__ */
241#define UTRACE(a,b,c)
242#endif
243
244/* Status of malloc. */
245static int malloc_active;
246
247/* Allocated memory. */
248static size_t malloc_used;
249
250/* My last break. */
251static void *malloc_brk;
252
253/* One location cache for free-list holders. */
254static struct pgfree *px;
255
256/* Compile-time options. */
257char *malloc_options;
258
259/* Name of the current public function. */
260static char *malloc_func;
261
262/* Macro for mmap. */
263#define MMAP(size) \
264 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
265 MMAP_FD, (off_t)0)
266
267/*
268 * Necessary function declarations.
269 */
270static void *imalloc(size_t size);
271static void ifree(void *ptr);
272static void *irealloc(void *ptr, size_t size);
273static void *malloc_bytes(size_t size);
274
275
276/*
277 * Function for page directory lookup.
278 */
279static int
280pdir_lookup(u_long index, struct pdinfo **pdi)
281{
282 struct pdinfo *spi;
283 u_long pidx = PI_IDX(index);
284
285 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
286 *pdi = last_dir;
287 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
288 *pdi = prev_dir;
289 else if (last_dir != NULL && prev_dir != NULL) {
290 if ((PD_IDX(last_dir->dirnum) > pidx) ?
291 (PD_IDX(last_dir->dirnum) - pidx):(pidx - PD_IDX(last_dir->dirnum))
292 < (PD_IDX(prev_dir->dirnum) > pidx) ?
293 (PD_IDX(prev_dir->dirnum) - pidx):(pidx - PD_IDX(prev_dir->dirnum)))
294 *pdi = last_dir;
295 else
296 *pdi = prev_dir;
297
298 if (PD_IDX((*pdi)->dirnum) > pidx) {
299 for (spi=(*pdi)->prev;spi!=NULL && PD_IDX(spi->dirnum)>pidx;
300 spi=spi->prev)
301 *pdi = spi;
302 if (spi != NULL)
303 *pdi = spi;
304 } else
305 for (spi=(*pdi)->next;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;
306 spi=spi->next)
307 *pdi = spi;
308 } else {
309 *pdi = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
310 for (spi=*pdi;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;spi=spi->next)
311 *pdi = spi;
312 }
313
314 return ((PD_IDX((*pdi)->dirnum) == pidx)?0:(PD_IDX((*pdi)->dirnum) > pidx)?1:-1);
315}
316
317
318#ifdef MALLOC_STATS
319void
320malloc_dump(FILE *fd)
321{
322 struct pginfo **pd;
323 struct pgfree *pf;
324 struct pdinfo *pi;
325 int j;
326
327 pd = page_dir;
328 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
329
330 /* print out all the pages */
331 for(j=0;j<=last_index;) {
332 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j);
333 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
334 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
335 if (!PI_OFF(++j)) {
336 if ((pi = pi->next) == NULL ||
337 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
338 pd = pi->base;
339 j += pdi_mod;
340 }
341 }
342 j--;
343 fprintf(fd, ".. %5d not mine\n", j);
344 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
345 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
346 if (!PI_OFF(++j)) {
347 if ((pi = pi->next) == NULL ||
348 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
349 pd = pi->base;
350 j += pdi_mod;
351 }
352 }
353 j--;
354 fprintf(fd, ".. %5d free\n", j);
355 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
356 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
357 if (!PI_OFF(++j)) {
358 if ((pi = pi->next) == NULL ||
359 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
360 pd = pi->base;
361 j += pdi_mod;
362 }
363 }
364 j--;
365 fprintf(fd, ".. %5d in use\n", j);
366 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
367 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]);
368 } else {
369 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
370 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total,
371 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
372 }
373 if (!PI_OFF(++j)) {
374 if ((pi = pi->next) == NULL)
375 break;
376 pd = pi->base;
377 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
378 }
379 }
380
381 for(pf=free_list.next; pf; pf=pf->next) {
382 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
383 pf, pf->page, pf->page + pf->size, pf->size,
384 pf->prev, pf->next);
385 if (pf == pf->next) {
386 fprintf(fd, "Free_list loops\n");
387 break;
388 }
389 }
390
391 /* print out various info */
392 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
393 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
394 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
395 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
396 fprintf(fd, "In use\t%lu\n", (u_long)malloc_used);
397}
398#endif /* MALLOC_STATS */
399
400extern char *__progname;
401
402static void
403wrterror(char *p)
404{
405 char *q = " error: ";
406 struct iovec iov[4];
407
408 iov[0].iov_base = __progname;
409 iov[0].iov_len = strlen(__progname);
410 iov[1].iov_base = malloc_func;
411 iov[1].iov_len = strlen(malloc_func);
412 iov[2].iov_base = q;
413 iov[2].iov_len = strlen(q);
414 iov[3].iov_base = p;
415 iov[3].iov_len = strlen(p);
416 writev(STDERR_FILENO, iov, 4);
417
418 suicide = 1;
419#ifdef MALLOC_STATS
420 if (malloc_stats)
421 malloc_dump(stderr);
422#endif /* MALLOC_STATS */
423 malloc_active--;
424 if (malloc_abort)
425 abort();
426}
427
428static void
429wrtwarning(char *p)
430{
431 char *q = " warning: ";
432 struct iovec iov[4];
433
434 if (malloc_abort)
435 wrterror(p);
436 else if (malloc_silent)
437 return;
438
439 iov[0].iov_base = __progname;
440 iov[0].iov_len = strlen(__progname);
441 iov[1].iov_base = malloc_func;
442 iov[1].iov_len = strlen(malloc_func);
443 iov[2].iov_base = q;
444 iov[2].iov_len = strlen(q);
445 iov[3].iov_base = p;
446 iov[3].iov_len = strlen(p);
447 writev(STDERR_FILENO, iov, 4);
448}
449
450#ifdef MALLOC_STATS
451static void
452malloc_exit(void)
453{
454 FILE *fd = fopen("malloc.out", "a");
455 char *q = "malloc() warning: Couldn't dump stats\n";
456 if (fd != NULL) {
457 malloc_dump(fd);
458 fclose(fd);
459 } else
460 write(STDERR_FILENO, q, strlen(q));
461}
462#endif /* MALLOC_STATS */
463
464
465/*
466 * Allocate a number of pages from the OS
467 */
468static void *
469map_pages(size_t pages)
470{
471 struct pdinfo *pi, *spi;
472 struct pginfo **pd;
473 u_long pidx,lidx;
474 void *result, *tail;
475 u_long index;
476
477 pages <<= malloc_pageshift;
478 result = MMAP(pages + malloc_guard);
479 if (result == MAP_FAILED) {
480 errno = ENOMEM;
481#ifdef MALLOC_EXTRA_SANITY
482 wrtwarning("(ES): map_pages fails\n");
483#endif /* MALLOC_EXTRA_SANITY */
484 return (NULL);
485 }
486 tail = result + pages + malloc_guard;
487 if (malloc_guard)
488 mprotect(result + pages, malloc_guard, PROT_NONE);
489
490 if (tail > malloc_brk)
491 malloc_brk = tail;
492 if ((index = ptr2index(tail) - 1) > last_index)
493 last_index = index;
494
495 /* Insert directory pages, if needed. */
496 pidx = PI_IDX(ptr2index(result));
497 lidx = PI_IDX(index);
498
499 pdir_lookup(ptr2index(result), &pi);
500
501 for (index=pidx,spi=pi;index<=lidx;index++) {
502 if (pi == NULL || PD_IDX(pi->dirnum) != index) {
503 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
504 errno = ENOMEM;
505 munmap(result, tail - result);
506#ifdef MALLOC_EXTRA_SANITY
507 wrtwarning("(ES): map_pages fails\n");
508#endif /* MALLOC_EXTRA_SANITY */
509 return (NULL);
510 }
511 memset(pd, 0, malloc_pagesize);
512 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
513 pi->base = pd;
514 pi->prev = spi;
515 pi->next = spi->next;
516 pi->dirnum = index * (malloc_pagesize/sizeof(struct pginfo *));
517
518 if (spi->next != NULL)
519 spi->next->prev = pi;
520 spi->next = pi;
521 }
522 if (index > pidx && index < lidx) {
523 pi->dirnum += pdi_mod;
524 } else if (index == pidx) {
525 if (pidx == lidx) {
526 pi->dirnum += (tail - result) >> malloc_pageshift;
527 } else {
528 pi->dirnum += pdi_mod - PI_OFF(ptr2index(result));
529 }
530 } else {
531 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
532 }
533#ifdef MALLOC_EXTRA_SANITY
534 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index) {
535 wrterror("(ES): pages directory overflow\n");
536 errno = EFAULT;
537 return (NULL);
538 }
539#endif /* MALLOC_EXTRA_SANITY */
540 if (index == pidx && pi != last_dir) {
541 prev_dir = last_dir;
542 last_dir = pi;
543 }
544 spi = pi;
545 pi = spi->next;
546 }
547
548 return (result);
549}
550
551
552/*
553 * Initialize the world
554 */
555static void
556malloc_init(void)
557{
558 char *p, b[64];
559 int i, j;
560 int save_errno = errno;
561
562 _MALLOC_LOCK_INIT();
563
564 INIT_MMAP();
565
566#ifdef MALLOC_EXTRA_SANITY
567 malloc_junk = 1;
568#endif /* MALLOC_EXTRA_SANITY */
569
570 for (i = 0; i < 3; i++) {
571 switch (i) {
572 case 0:
573 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
574 if (j <= 0)
575 continue;
576 b[j] = '\0';
577 p = b;
578 break;
579
580 case 1:
581 if (issetugid() == 0)
582 p = getenv("MALLOC_OPTIONS");
583 else
584 continue;
585 break;
586
587 case 2:
588 p = malloc_options;
589 break;
590
591 default: p = NULL;
592 }
593 for (; p != NULL && *p != '\0'; p++) {
594 switch (*p) {
595 case '>': malloc_cache <<= 1; break;
596 case '<': malloc_cache >>= 1; break;
597 case 'a': malloc_abort = 0; break;
598 case 'A': malloc_abort = 1; break;
599#ifdef MALLOC_STATS
600 case 'd': malloc_stats = 0; break;
601 case 'D': malloc_stats = 1; break;
602#endif /* MALLOC_STATS */
603 case 'f': malloc_freeprot = 0; break;
604 case 'F': malloc_freeprot = 1; break;
605 case 'g': malloc_guard = 0; break;
606 case 'G': malloc_guard = malloc_pagesize; break;
607#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
608 case 'h': malloc_hint = 0; break;
609 case 'H': malloc_hint = 1; break;
610#endif /* __FreeBSD__ */
611 case 'j': malloc_junk = 0; break;
612 case 'J': malloc_junk = 1; break;
613 case 'n': malloc_silent = 0; break;
614 case 'N': malloc_silent = 1; break;
615 case 'r': malloc_realloc = 0; break;
616 case 'R': malloc_realloc = 1; break;
617#ifdef __FreeBSD__
618 case 'u': malloc_utrace = 0; break;
619 case 'U': malloc_utrace = 1; break;
620#endif /* __FreeBSD__ */
621 case 'x': malloc_xmalloc = 0; break;
622 case 'X': malloc_xmalloc = 1; break;
623 case 'z': malloc_zero = 0; break;
624 case 'Z': malloc_zero = 1; break;
625 default:
626 j = malloc_abort;
627 malloc_abort = 0;
628 wrtwarning("unknown char in MALLOC_OPTIONS\n");
629 malloc_abort = j;
630 break;
631 }
632 }
633 }
634
635 UTRACE(0, 0, 0);
636
637 /*
638 * We want junk in the entire allocation, and zero only in the part
639 * the user asked for.
640 */
641 if (malloc_zero)
642 malloc_junk=1;
643
644#ifdef MALLOC_STATS
645 if (malloc_stats && (atexit(malloc_exit) == -1))
646 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n");
647#endif /* MALLOC_STATS */
648
649 /* Allocate one page for the page directory. */
650 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
651
652 if (page_dir == MAP_FAILED) {
653 wrterror("mmap(2) failed, check limits\n");
654 errno = ENOMEM;
655 return;
656 }
657
658 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
659 pdi_mod = pdi_off / sizeof(struct pginfo *);
660
661 last_dir = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
662 last_dir->base = page_dir;
663 last_dir->prev = last_dir->next = NULL;
664 last_dir->dirnum = malloc_pageshift;
665
666 /* Been here, done that. */
667 malloc_started++;
668
669 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
670
671 if (!malloc_cache)
672 malloc_cache++;
673
674 malloc_cache <<= malloc_pageshift;
675
676 errno = save_errno;
677}
678
679/*
680 * Allocate a number of complete pages
681 */
682static void *
683malloc_pages(size_t size)
684{
685 void *p, *delay_free = NULL;
686 int i;
687 struct rlimit rl;
688 struct pginfo **pd;
689 struct pdinfo *pi;
690 u_long pidx;
691 void *tp;
692 struct pgfree *pf;
693 u_long index;
694 int m;
695
696 size = pageround(size) + malloc_guard;
697
698 p = NULL;
699 /* Look for free pages before asking for more */
700 for (pf = free_list.next; pf; pf = pf->next) {
701
702#ifdef MALLOC_EXTRA_SANITY
703 if (pf->size & malloc_pagemask) {
704 wrterror("(ES): junk length entry on free_list\n");
705 errno = EFAULT;
706 return (NULL);
707 }
708 if (!pf->size) {
709 wrterror("(ES): zero length entry on free_list\n");
710 errno = EFAULT;
711 return (NULL);
712 }
713 if (pf->page > (pf->page + pf->size)) {
714 wrterror("(ES): sick entry on free_list\n");
715 errno = EFAULT;
716 return (NULL);
717 }
718 if ((pi = pf->pdir) == NULL) {
719 wrterror("(ES): invalid page directory on free-list\n");
720 errno = EFAULT;
721 return (NULL);
722 }
723 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
724 wrterror("(ES): directory index mismatch on free-list\n");
725 errno = EFAULT;
726 return (NULL);
727 }
728 pd = pi->base;
729 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
730 wrterror("(ES): non-free first page on free-list\n");
731 errno = EFAULT;
732 return (NULL);
733 }
734 pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1);
735 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
736 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
737 wrterror("(ES): last page not referenced in page directory\n");
738 errno = EFAULT;
739 return (NULL);
740 }
741 pd = pi->base;
742 if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE) {
743 wrterror("(ES): non-free last page on free-list\n");
744 errno = EFAULT;
745 return (NULL);
746 }
747#endif /* MALLOC_EXTRA_SANITY */
748
749 if (pf->size < size)
750 continue;
751
752 if (pf->size == size) {
753 p = pf->page;
754 pi = pf->pdir;
755 if (pf->next != NULL)
756 pf->next->prev = pf->prev;
757 pf->prev->next = pf->next;
758 delay_free = pf;
759 break;
760 }
761
762 p = pf->page;
763 pf->page = (char *)pf->page + size;
764 pf->size -= size;
765 pidx = PI_IDX(ptr2index(pf->page));
766 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
767 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
768 wrterror("(ES): hole in directories\n");
769 errno = EFAULT;
770 return (NULL);
771 }
772 tp = pf->pdir;
773 pf->pdir = pi;
774 pi = tp;
775 break;
776 }
777
778 size -= malloc_guard;
779
780#ifdef MALLOC_EXTRA_SANITY
781 if (p != NULL && pi != NULL) {
782 pidx = PD_IDX(pi->dirnum);
783 pd = pi->base;
784 }
785 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
786 wrterror("(ES): allocated non-free page on free-list\n");
787 errno = EFAULT;
788 return (NULL);
789 }
790#endif /* MALLOC_EXTRA_SANITY */
791
792 if (p != NULL && (malloc_guard || malloc_freeprot))
793 mprotect(p, size, PROT_READ|PROT_WRITE);
794
795 size >>= malloc_pageshift;
796
797 /* Map new pages */
798 if (p == NULL)
799 p = map_pages(size);
800
801 if (p != NULL) {
802
803 index = ptr2index(p);
804 pidx = PI_IDX(index);
805 pdir_lookup(index, &pi);
806#ifdef MALLOC_EXTRA_SANITY
807 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
808 wrterror("(ES): mapped pages not found in directory\n");
809 errno = EFAULT;
810 return (NULL);
811 }
812#endif /* MALLOC_EXTRA_SANITY */
813 if (pi != last_dir) {
814 prev_dir = last_dir;
815 last_dir = pi;
816 }
817 pd = pi->base;
818 pd[PI_OFF(index)] = MALLOC_FIRST;
819 for (i=1;i<size;i++) {
820 if (!PI_OFF(index+i)) {
821 pidx++;
822 pi = pi->next;
823#ifdef MALLOC_EXTRA_SANITY
824 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
825 wrterror("(ES): hole in mapped pages directory\n");
826 errno = EFAULT;
827 return (NULL);
828 }
829#endif /* MALLOC_EXTRA_SANITY */
830 pd = pi->base;
831 }
832 pd[PI_OFF(index+i)] = MALLOC_FOLLOW;
833 }
834 if (malloc_guard) {
835 if (!PI_OFF(index+i)) {
836 pidx++;
837 pi = pi->next;
838#ifdef MALLOC_EXTRA_SANITY
839 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
840 wrterror("(ES): hole in mapped pages directory\n");
841 errno = EFAULT;
842 return (NULL);
843 }
844#endif /* MALLOC_EXTRA_SANITY */
845 pd = pi->base;
846 }
847 pd[PI_OFF(index+i)] = MALLOC_FIRST;
848 }
849
850 malloc_used += size << malloc_pageshift;
851
852 if (malloc_junk)
853 memset(p, SOME_JUNK, size << malloc_pageshift);
854 }
855
856 if (delay_free) {
857 if (px == NULL)
858 px = delay_free;
859 else
860 ifree(delay_free);
861 }
862
863 return (p);
864}
865
866/*
867 * Allocate a page of fragments
868 */
869
870static __inline__ int
871malloc_make_chunks(int bits)
872{
873 struct pginfo *bp;
874 struct pginfo **pd;
875 struct pdinfo *pi;
876 u_long pidx;
877 void *pp;
878 int i, k, l;
879
880 /* Allocate a new bucket */
881 pp = malloc_pages((size_t)malloc_pagesize);
882 if (pp == NULL)
883 return (0);
884
885 /* Find length of admin structure */
886 l = sizeof *bp - sizeof(u_long);
887 l += sizeof(u_long) *
888 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
889
890 /* Don't waste more than two chunks on this */
891 /*
892 * If we are to allocate a memory protected page for the malloc(0)
893 * case (when bits=0), it must be from a different page than the
894 * pginfo page.
895 * --> Treat it like the big chunk alloc, get a second data page.
896 */
897 if (bits != 0 && (1UL<<(bits)) <= l+l) {
898 bp = (struct pginfo *)pp;
899 } else {
900 bp = (struct pginfo *)imalloc(l);
901 if (bp == NULL) {
902 ifree(pp);
903 return (0);
904 }
905 }
906
907 /* memory protect the page allocated in the malloc(0) case */
908 if (bits == 0) {
909
910 bp->size = 0;
911 bp->shift = 1;
912 i = malloc_minsize-1;
913 while (i >>= 1)
914 bp->shift++;
915 bp->total = bp->free = malloc_pagesize >> bp->shift;
916 bp->page = pp;
917
918 k = mprotect(pp, malloc_pagesize, PROT_NONE);
919 if (k < 0) {
920 ifree(pp);
921 ifree(bp);
922 return (0);
923 }
924 } else {
925 bp->size = (1UL<<bits);
926 bp->shift = bits;
927 bp->total = bp->free = malloc_pagesize >> bits;
928 bp->page = pp;
929 }
930
931 /* set all valid bits in the bitmap */
932 k = bp->total;
933 i = 0;
934
935 /* Do a bunch at a time */
936 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
937 bp->bits[i / MALLOC_BITS] = ~0UL;
938
939 for(; i < k; i++)
940 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
941
942 if (bp == bp->page) {
943 /* Mark the ones we stole for ourselves */
944 for(i=0;l > 0;i++) {
945 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
946 bp->free--;
947 bp->total--;
948 l -= (1 << bits);
949 }
950 }
951
952 /* MALLOC_LOCK */
953
954 pidx = PI_IDX(ptr2index(pp));
955 pdir_lookup(ptr2index(pp), &pi);
956#ifdef MALLOC_EXTRA_SANITY
957 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
958 wrterror("(ES): mapped pages not found in directory\n");
959 errno = EFAULT;
960 return (0);
961 }
962#endif /* MALLOC_EXTRA_SANITY */
963 if (pi != last_dir) {
964 prev_dir = last_dir;
965 last_dir = pi;
966 }
967 pd = pi->base;
968 pd[PI_OFF(ptr2index(pp))] = bp;
969
970 bp->next = page_dir[bits];
971 page_dir[bits] = bp;
972
973 /* MALLOC_UNLOCK */
974
975 return (1);
976}
977
978/*
979 * Allocate a fragment
980 */
981static void *
982malloc_bytes(size_t size)
983{
984 int i,j;
985 u_long u;
986 struct pginfo *bp;
987 int k;
988 u_long *lp;
989
990 /* Don't bother with anything less than this */
991 /* unless we have a malloc(0) requests */
992 if (size != 0 && size < malloc_minsize)
993 size = malloc_minsize;
994
995 /* Find the right bucket */
996 if (size == 0)
997 j=0;
998 else {
999 j = 1;
1000 i = size-1;
1001 while (i >>= 1)
1002 j++;
1003 }
1004
1005 /* If it's empty, make a page more of that size chunks */
1006 if (page_dir[j] == NULL && !malloc_make_chunks(j))
1007 return (NULL);
1008
1009 bp = page_dir[j];
1010
1011 /* Find first word of bitmap which isn't empty */
1012 for (lp = bp->bits; !*lp; lp++)
1013 ;
1014
1015 /* Find that bit, and tweak it */
1016 u = 1;
1017 k = 0;
1018 while (!(*lp & u)) {
1019 u += u;
1020 k++;
1021 }
1022
1023 if (malloc_guard) {
1024 /* Walk to a random position. */
1025 i = arc4random() % bp->free;
1026 while (i > 0) {
1027 u += u;
1028 k++;
1029 if (k >= MALLOC_BITS) {
1030 lp++;
1031 u = 1;
1032 k = 0;
1033 }
1034#ifdef MALLOC_EXTRA_SANITY
1035 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1036 wrterror("chunk overflow\n");
1037 errno = EFAULT;
1038 return (NULL);
1039 }
1040#endif /* MALLOC_EXTRA_SANITY */
1041 if (*lp & u)
1042 i--;
1043 }
1044 }
1045 *lp ^= u;
1046
1047 /* If there are no more free, remove from free-list */
1048 if (!--bp->free) {
1049 page_dir[j] = bp->next;
1050 bp->next = NULL;
1051 }
1052
1053 /* Adjust to the real offset of that chunk */
1054 k += (lp-bp->bits)*MALLOC_BITS;
1055 k <<= bp->shift;
1056
1057 if (malloc_junk && bp->size != 0)
1058 memset((char *)bp->page + k, SOME_JUNK, bp->size);
1059
1060 return ((u_char *)bp->page + k);
1061}
1062
1063/*
1064 * Allocate a piece of memory
1065 */
1066static void *
1067imalloc(size_t size)
1068{
1069 void *result;
1070 int ptralloc = 0;
1071
1072 if (!malloc_started)
1073 malloc_init();
1074
1075 if (suicide)
1076 abort();
1077
1078 if ((size + malloc_pagesize) < size) { /* Check for overflow */
1079 result = NULL;
1080 errno = ENOMEM;
1081 }
1082 else if (size <= malloc_maxsize)
1083 result = malloc_bytes(size);
1084 else
1085 result = malloc_pages(size);
1086
1087 if (malloc_abort == 1 && result == NULL)
1088 wrterror("allocation failed\n");
1089
1090 if (malloc_zero && result != NULL)
1091 memset(result, 0, size);
1092
1093 return (result);
1094}
1095
1096/*
1097 * Change the size of an allocation.
1098 */
1099static void *
1100irealloc(void *ptr, size_t size)
1101{
1102 void *p;
1103 u_long osize, index, i;
1104 struct pginfo **mp;
1105 struct pginfo **pd;
1106 struct pdinfo *pi;
1107 u_long pidx;
1108
1109 if (suicide)
1110 abort();
1111
1112 if (!malloc_started) {
1113 wrtwarning("malloc() has never been called\n");
1114 return (NULL);
1115 }
1116
1117 index = ptr2index(ptr);
1118
1119 if (index < malloc_pageshift) {
1120 wrtwarning("junk pointer, too low to make sense\n");
1121 return (NULL);
1122 }
1123
1124 if (index > last_index) {
1125 wrtwarning("junk pointer, too high to make sense\n");
1126 return (NULL);
1127 }
1128
1129 pidx = PI_IDX(index);
1130 pdir_lookup(index, &pi);
1131#ifdef MALLOC_EXTRA_SANITY
1132 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1133 wrterror("(ES): mapped pages not found in directory\n");
1134 errno = EFAULT;
1135 return (NULL);
1136 }
1137#endif /* MALLOC_EXTRA_SANITY */
1138 if (pi != last_dir) {
1139 prev_dir = last_dir;
1140 last_dir = pi;
1141 }
1142
1143 pd = pi->base;
1144 mp = &pd[PI_OFF(index)];
1145
1146 if (*mp == MALLOC_FIRST) { /* Page allocation */
1147
1148 /* Check the pointer */
1149 if ((u_long)ptr & malloc_pagemask) {
1150 wrtwarning("modified (page-) pointer\n");
1151 return (NULL);
1152 }
1153
1154 /* Find the size in bytes */
1155 i = index;
1156 if (!PI_OFF(++i)) {
1157 pi = pi->next;
1158 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1159 pi = NULL;
1160 if (pi != NULL)
1161 pd = pi->base;
1162 }
1163 for (osize = malloc_pagesize;
1164 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1165 osize += malloc_pagesize;
1166 if (!PI_OFF(++i)) {
1167 pi = pi->next;
1168 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1169 pi = NULL;
1170 if (pi != NULL)
1171 pd = pi->base;
1172 }
1173 }
1174
1175 if (!malloc_realloc && /* Unless we have to, */
1176 size <= osize && /* .. or are too small, */
1177 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
1178 if (malloc_junk)
1179 memset((char *)ptr + size, SOME_JUNK, osize-size);
1180 return (ptr); /* ..don't do anything else. */
1181 }
1182
1183 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
1184
1185 /* Check the pointer for sane values */
1186 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
1187 wrtwarning("modified (chunk-) pointer\n");
1188 return (NULL);
1189 }
1190
1191 /* Find the chunk index in the page */
1192 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
1193
1194 /* Verify that it isn't a free chunk already */
1195 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1196 wrtwarning("chunk is already free\n");
1197 return (NULL);
1198 }
1199
1200 osize = (*mp)->size;
1201
1202 if (!malloc_realloc && /* Unless we have to, */
1203 size <= osize && /* ..or are too small, */
1204 (size > osize/2 || /* ..or could use a smaller size, */
1205 osize == malloc_minsize)) { /* ..(if there is one) */
1206 if (malloc_junk)
1207 memset((char *)ptr + size, SOME_JUNK, osize-size);
1208 return (ptr); /* ..don't do anything else. */
1209 }
1210
1211 } else {
1212 wrtwarning("pointer to wrong page\n");
1213 return (NULL);
1214 }
1215
1216 p = imalloc(size);
1217
1218 if (p != NULL) {
1219 /* copy the lesser of the two sizes, and free the old one */
1220 /* Don't move from/to 0 sized region !!! */
1221 if (osize != 0 && size != 0) {
1222 if (osize < size)
1223 memcpy(p, ptr, osize);
1224 else
1225 memcpy(p, ptr, size);
1226 }
1227 ifree(ptr);
1228 }
1229
1230 return (p);
1231}
1232
1233/*
1234 * Free a sequence of pages
1235 */
1236
1237static __inline__ void
1238free_pages(void *ptr, u_long index, struct pginfo *info)
1239{
1240 u_long i, l;
1241 struct pginfo **pd;
1242 struct pdinfo *pi, *spi;
1243 u_long pidx, lidx;
1244 struct pgfree *pf, *pt=NULL;
1245 void *tail;
1246
1247 if (info == MALLOC_FREE) {
1248 wrtwarning("page is already free\n");
1249 return;
1250 }
1251
1252 if (info != MALLOC_FIRST) {
1253 wrtwarning("pointer to wrong page\n");
1254 return;
1255 }
1256
1257 if ((u_long)ptr & malloc_pagemask) {
1258 wrtwarning("modified (page-) pointer\n");
1259 return;
1260 }
1261
1262 /* Count how many pages and mark them free at the same time */
1263 pidx = PI_IDX(index);
1264 pdir_lookup(index, &pi);
1265#ifdef MALLOC_EXTRA_SANITY
1266 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1267 wrterror("(ES): mapped pages not found in directory\n");
1268 errno = EFAULT;
1269 return;
1270 }
1271#endif /* MALLOC_EXTRA_SANITY */
1272
1273 spi = pi; /* Save page index for start of region. */
1274
1275 pd = pi->base;
1276 pd[PI_OFF(index)] = MALLOC_FREE;
1277 i = 1;
1278 if (!PI_OFF(index+i)) {
1279 pi = pi->next;
1280 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1281 pi = NULL;
1282 else
1283 pd = pi->base;
1284 }
1285 while (pi != NULL && pd[PI_OFF(index+i)] == MALLOC_FOLLOW) {
1286 pd[PI_OFF(index+i)] = MALLOC_FREE;
1287 i++;
1288 if (!PI_OFF(index+i)) {
1289 if ((pi=pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1290 pi = NULL;
1291 else
1292 pd = pi->base;
1293 }
1294 }
1295
1296 l = i << malloc_pageshift;
1297
1298 if (malloc_junk)
1299 memset(ptr, SOME_JUNK, l);
1300
1301 malloc_used -= l;
1302 if (malloc_guard) {
1303#ifdef MALLOC_EXTRA_SANITY
1304 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) {
1305 wrterror("(ES): hole in mapped pages directory\n");
1306 errno = EFAULT;
1307 return;
1308 }
1309#endif /* MALLOC_EXTRA_SANITY */
1310 pd[PI_OFF(index+i)] = MALLOC_FREE;
1311 l += malloc_guard;
1312 }
1313 tail = (char *)ptr + l;
1314
1315#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1316 if (malloc_hint)
1317 madvise(ptr, l, MADV_FREE);
1318#endif
1319
1320 if (malloc_freeprot)
1321 mprotect(ptr, l, PROT_NONE);
1322
1323 /* Add to free-list. */
1324 if (px == NULL)
1325 px = imalloc(sizeof *px); /* This cannot fail... */
1326 px->page = ptr;
1327 px->pdir = spi;
1328 px->size = l;
1329
1330 if (free_list.next == NULL) {
1331
1332 /* Nothing on free list, put this at head. */
1333 px->next = NULL;
1334 px->prev = &free_list;
1335 free_list.next = px;
1336 pf = px;
1337 px = NULL;
1338
1339 } else {
1340
1341 /* Find the right spot, leave pf pointing to the modified entry. */
1342
1343 for(pf = free_list.next; (pf->page+pf->size) < ptr && pf->next != NULL;
1344 pf = pf->next)
1345 ; /* Race ahead here. */
1346
1347 if (pf->page > tail) {
1348 /* Insert before entry */
1349 px->next = pf;
1350 px->prev = pf->prev;
1351 pf->prev = px;
1352 px->prev->next = px;
1353 pf = px;
1354 px = NULL;
1355 } else if ((pf->page + pf->size) == ptr ) {
1356 /* Append to the previous entry. */
1357 pf->size += l;
1358 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page ) {
1359 /* And collapse the next too. */
1360 pt = pf->next;
1361 pf->size += pt->size;
1362 pf->next = pt->next;
1363 if (pf->next != NULL)
1364 pf->next->prev = pf;
1365 }
1366 } else if (pf->page == tail) {
1367 /* Prepend to entry. */
1368 pf->size += l;
1369 pf->page = ptr;
1370 pf->pdir = spi;
1371 } else if (pf->next == NULL) {
1372 /* Append at tail of chain. */
1373 px->next = NULL;
1374 px->prev = pf;
1375 pf->next = px;
1376 pf = px;
1377 px = NULL;
1378 } else {
1379 wrterror("freelist is destroyed\n");
1380 errno = EFAULT;
1381 return;
1382 }
1383 }
1384
1385 if (pf->pdir != last_dir) {
1386 prev_dir = last_dir;
1387 last_dir = pf->pdir;
1388 }
1389
1390 /* Return something to OS ? */
1391 if (pf->next == NULL && /* If we're the last one, */
1392 pf->size > malloc_cache && /* ..and the cache is full, */
1393 (pf->page + pf->size) == malloc_brk) { /* ..and none behind us, */
1394
1395 /*
1396 * Keep the cache intact. Notice that the '>' above guarantees that
1397 * the pf will always have at least one page afterwards.
1398 */
1399 if (munmap((char *)pf->page + malloc_cache, pf->size - malloc_cache)!=0)
1400 goto not_return;
1401 tail = pf->page + pf->size;
1402 lidx = ptr2index(tail) - 1;
1403 pf->size = malloc_cache;
1404
1405 malloc_brk = pf->page + malloc_cache;
1406
1407 index = ptr2index(malloc_brk);
1408
1409 pidx = PI_IDX(index);
1410 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1411 prev_dir = NULL; /* Will be wiped out below ! */
1412
1413 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
1414
1415 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1416 pd = pi->base;
1417
1418 for(i=index;i <= last_index;) {
1419 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1420 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1421#ifdef MALLOC_EXTRA_SANITY
1422 if (!PD_OFF(pi->dirnum)) {
1423 wrterror("(ES): pages directory underflow\n");
1424 errno = EFAULT;
1425 return;
1426 }
1427#endif /* MALLOC_EXTRA_SANITY */
1428 pi->dirnum--;
1429 }
1430 i++;
1431 if (!PI_OFF(i)) {
1432 /* If no page in that dir, free directory page. */
1433 if (!PD_OFF(pi->dirnum)) {
1434 /* Remove from list. */
1435 pi->prev->next = pi->next;
1436 if (pi->next != NULL)
1437 pi->next->prev = pi->prev;
1438 pi = pi->next;
1439 munmap(pd, malloc_pagesize);
1440 } else
1441 pi = pi->next;
1442 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1443 break;
1444 pd = pi->base;
1445 }
1446 }
1447 }
1448
1449 last_index = index - 1;
1450
1451 /* XXX: We could realloc/shrink the pagedir here I guess. */
1452 }
1453not_return:
1454 if (pt != NULL)
1455 ifree(pt);
1456}
1457
1458/*
1459 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1460 */
1461
1462/* ARGSUSED */
1463static __inline__ void
1464free_bytes(void *ptr, int index, struct pginfo *info)
1465{
1466 int i;
1467 struct pginfo **mp;
1468 struct pginfo **pd;
1469 struct pdinfo *pi;
1470 u_long pidx;
1471 void *vp;
1472
1473 /* Find the chunk number on the page */
1474 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
1475
1476 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
1477 wrtwarning("modified (chunk-) pointer\n");
1478 return;
1479 }
1480
1481 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1482 wrtwarning("chunk is already free\n");
1483 return;
1484 }
1485
1486 if (malloc_junk && info->size != 0)
1487 memset(ptr, SOME_JUNK, info->size);
1488
1489 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1490 info->free++;
1491
1492 if (info->size != 0)
1493 mp = page_dir + info->shift;
1494 else
1495 mp = page_dir;
1496
1497 if (info->free == 1) {
1498
1499 /* Page became non-full */
1500
1501 /* Insert in address order */
1502 while (*mp != NULL && (*mp)->next != NULL &&
1503 (*mp)->next->page < info->page)
1504 mp = &(*mp)->next;
1505 info->next = *mp;
1506 *mp = info;
1507 return;
1508 }
1509
1510 if (info->free != info->total)
1511 return;
1512
1513 /* Find & remove this page in the queue */
1514 while (*mp != info) {
1515 mp = &((*mp)->next);
1516#ifdef MALLOC_EXTRA_SANITY
1517 if (!*mp) {
1518 wrterror("(ES): Not on queue\n");
1519 errno = EFAULT;
1520 return;
1521 }
1522#endif /* MALLOC_EXTRA_SANITY */
1523 }
1524 *mp = info->next;
1525
1526 /* Free the page & the info structure if need be */
1527 pidx = PI_IDX(ptr2index(info->page));
1528 pdir_lookup(ptr2index(info->page), &pi);
1529#ifdef MALLOC_EXTRA_SANITY
1530 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1531 wrterror("(ES): mapped pages not found in directory\n");
1532 errno = EFAULT;
1533 return;
1534 }
1535#endif /* MALLOC_EXTRA_SANITY */
1536 if (pi != last_dir) {
1537 prev_dir = last_dir;
1538 last_dir = pi;
1539 }
1540
1541 pd = pi->base;
1542 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1543
1544 /* If the page was mprotected, unprotect it before releasing it */
1545 if (info->size == 0) {
1546 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1547 /* Do we have to care if mprotect succeeds here ? */
1548 }
1549
1550 vp = info->page; /* Order is important ! */
1551 if(vp != (void*)info)
1552 ifree(info);
1553 ifree(vp);
1554}
1555
1556static void
1557ifree(void *ptr)
1558{
1559 struct pginfo *info;
1560 struct pginfo **pd;
1561 struct pdinfo *pi;
1562 u_long pidx;
1563 u_long index;
1564
1565 /* This is legal */
1566 if (ptr == NULL)
1567 return;
1568
1569 if (!malloc_started) {
1570 wrtwarning("malloc() has never been called\n");
1571 return;
1572 }
1573
1574 /* If we're already sinking, don't make matters any worse. */
1575 if (suicide)
1576 return;
1577
1578 index = ptr2index(ptr);
1579
1580 if (index < malloc_pageshift) {
1581 wrtwarning("junk pointer, too low to make sense\n");
1582 return;
1583 }
1584
1585 if (index > last_index) {
1586 wrtwarning("junk pointer, too high to make sense\n");
1587 return;
1588 }
1589
1590 pidx = PI_IDX(index);
1591 pdir_lookup(index, &pi);
1592#ifdef MALLOC_EXTRA_SANITY
1593 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1594 wrterror("(ES): mapped pages not found in directory\n");
1595 errno = EFAULT;
1596 return;
1597 }
1598#endif /* MALLOC_EXTRA_SANITY */
1599 if (pi != last_dir) {
1600 prev_dir = last_dir;
1601 last_dir = pi;
1602 }
1603
1604 pd = pi->base;
1605 info = pd[PI_OFF(index)];
1606
1607 if (info < MALLOC_MAGIC)
1608 free_pages(ptr, index, info);
1609 else
1610 free_bytes(ptr, index, info);
1611 return;
1612}
1613
1614/*
1615 * Common function for handling recursion. Only
1616 * print the error message once, to avoid making the problem
1617 * potentially worse.
1618 */
1619static void
1620malloc_recurse(void)
1621{
1622 static int noprint;
1623
1624 if (noprint == 0) {
1625 noprint = 1;
1626 wrtwarning("recursive call\n");
1627 }
1628 malloc_active--;
1629 _MALLOC_UNLOCK();
1630 errno = EDEADLK;
1631}
1632
1633/*
1634 * These are the public exported interface routines.
1635 */
1636void *
1637malloc(size_t size)
1638{
1639 void *r;
1640
1641 _MALLOC_LOCK();
1642 malloc_func = " in malloc():";
1643 if (malloc_active++) {
1644 malloc_recurse();
1645 return (NULL);
1646 }
1647 r = imalloc(size);
1648 UTRACE(0, size, r);
1649 malloc_active--;
1650 _MALLOC_UNLOCK();
1651 if (malloc_xmalloc && r == NULL) {
1652 wrterror("out of memory\n");
1653 errno = ENOMEM;
1654 }
1655 return (r);
1656}
1657
1658void
1659free(void *ptr)
1660{
1661 _MALLOC_LOCK();
1662 malloc_func = " in free():";
1663 if (malloc_active++) {
1664 malloc_recurse();
1665 return;
1666 }
1667 ifree(ptr);
1668 UTRACE(ptr, 0, 0);
1669 malloc_active--;
1670 _MALLOC_UNLOCK();
1671 return;
1672}
1673
1674void *
1675realloc(void *ptr, size_t size)
1676{
1677 void *r;
1678
1679 _MALLOC_LOCK();
1680 malloc_func = " in realloc():";
1681 if (malloc_active++) {
1682 malloc_recurse();
1683 return (NULL);
1684 }
1685 if (ptr == NULL) {
1686 r = imalloc(size);
1687 } else {
1688 r = irealloc(ptr, size);
1689 }
1690 UTRACE(ptr, size, r);
1691 malloc_active--;
1692 _MALLOC_UNLOCK();
1693 if (malloc_xmalloc && r == NULL) {
1694 wrterror("out of memory\n");
1695 errno = ENOMEM;
1696 }
1697 return (r);
1698}
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000000..b193ae345c
--- /dev/null
+++ b/src/lib/libc/stdlib/merge.c
@@ -0,0 +1,336 @@
1/*-
2 * Copyright (c) 1992, 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 * Peter McIlroy.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: merge.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37/*
38 * Hybrid exponential search/linear search merge sort with hybrid
39 * natural/pairwise first pass. Requires about .3% more comparisons
40 * for random data than LSMS with pairwise first pass alone.
41 * It works for objects as small as two bytes.
42 */
43
44#define NATURAL
45#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
46
47/* #define NATURAL to get hybrid natural merge.
48 * (The default is pairwise merging.)
49 */
50
51#include <sys/types.h>
52
53#include <errno.h>
54#include <stdlib.h>
55#include <string.h>
56
57static void setup(u_char *, u_char *, size_t, size_t, int (*)());
58static void insertionsort(u_char *, size_t, size_t, int (*)());
59
60#define ISIZE sizeof(int)
61#define PSIZE sizeof(u_char *)
62#define ICOPY_LIST(src, dst, last) \
63 do \
64 *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
65 while(src < last)
66#define ICOPY_ELT(src, dst, i) \
67 do \
68 *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
69 while (i -= ISIZE)
70
71#define CCOPY_LIST(src, dst, last) \
72 do \
73 *dst++ = *src++; \
74 while (src < last)
75#define CCOPY_ELT(src, dst, i) \
76 do \
77 *dst++ = *src++; \
78 while (i -= 1)
79
80/*
81 * Find the next possible pointer head. (Trickery for forcing an array
82 * to do double duty as a linked list when objects do not align with word
83 * boundaries.
84 */
85/* Assumption: PSIZE is a power of 2. */
86#define EVAL(p) (u_char **) \
87 ((u_char *)0 + \
88 (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
89
90/*
91 * Arguments are as for qsort.
92 */
93int
94mergesort(void *base, size_t nmemb, size_t size,
95 int (*cmp)(const void *, const void *))
96{
97 int i, sense;
98 int big, iflag;
99 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
100 u_char *list2, *list1, *p2, *p, *last, **p1;
101
102 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
103 errno = EINVAL;
104 return (-1);
105 }
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, tmp, sense;
255 u_char *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/mrand48.c b/src/lib/libc/stdlib/mrand48.c
new file mode 100644
index 0000000000..cd34260b5c
--- /dev/null
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -0,0 +1,27 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: mrand48.c,v 1.2 1996/08/19 08:33:39 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22long
23mrand48(void)
24{
25 __dorand48(__rand48_seed);
26 return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1];
27}
diff --git a/src/lib/libc/stdlib/multibyte.c b/src/lib/libc/stdlib/multibyte.c
new file mode 100644
index 0000000000..ba878b8fdc
--- /dev/null
+++ b/src/lib/libc/stdlib/multibyte.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: multibyte.c,v 1.4 2003/06/02 20:18:38 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36/*
37 * Stub multibyte character functions.
38 * This cheezy implementation is fixed to the native single-byte
39 * character set.
40 */
41
42int
43mblen(s, n)
44 const char *s;
45 size_t n;
46{
47 if (s == NULL || *s == '\0')
48 return 0;
49 if (n == 0)
50 return -1;
51 return 1;
52}
53
54/*ARGSUSED*/
55int
56mbtowc(pwc, s, n)
57 wchar_t *pwc;
58 const char *s;
59 size_t n;
60{
61 if (s == NULL)
62 return 0;
63 if (n == 0)
64 return -1;
65 if (pwc)
66 *pwc = (wchar_t) *s;
67 return (*s != '\0');
68}
69
70/*ARGSUSED*/
71int
72wctomb(char *s, wchar_t wchar)
73{
74 if (s == NULL)
75 return 0;
76
77 *s = (char) wchar;
78 return 1;
79}
80
81/*ARGSUSED*/
82size_t
83mbstowcs(pwcs, s, n)
84 wchar_t *pwcs;
85 const char *s;
86 size_t n;
87{
88 int count = 0;
89
90 if (n != 0) {
91 do {
92 if ((*pwcs++ = (wchar_t) *s++) == 0)
93 break;
94 count++;
95 } while (--n != 0);
96 }
97
98 return count;
99}
100
101/*ARGSUSED*/
102size_t
103wcstombs(s, pwcs, n)
104 char *s;
105 const wchar_t *pwcs;
106 size_t n;
107{
108 int count = 0;
109
110 if (n != 0) {
111 do {
112 if ((*s++ = (char) *pwcs++) == 0)
113 break;
114 count++;
115 } while (--n != 0);
116 }
117
118 return count;
119}
120
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
new file mode 100644
index 0000000000..b1ec2cebb1
--- /dev/null
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -0,0 +1,25 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: nrand48.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20long
21nrand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
25}
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c
new file mode 100644
index 0000000000..231982bf87
--- /dev/null
+++ b/src/lib/libc/stdlib/putenv.c
@@ -0,0 +1,53 @@
1/*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: putenv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37int
38putenv(const char *str)
39{
40 char *p, *equal;
41 int rval;
42
43 if ((p = strdup(str)) == NULL)
44 return (-1);
45 if ((equal = strchr(p, '=')) == NULL) {
46 (void)free(p);
47 return (-1);
48 }
49 *equal = '\0';
50 rval = setenv(p, equal + 1, 1);
51 (void)free(p);
52 return (rval);
53}
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
new file mode 100644
index 0000000000..093212edf5
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.3
@@ -0,0 +1,56 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qabs.3,v 1.6 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt QABS 3
36.Os
37.Sh NAME
38.Nm qabs
39.Nd return the absolute value of a quad integer
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft quad_t
43.Fn qabs "quad_t j"
44.Sh DESCRIPTION
45The
46.Fn qabs
47function returns the absolute value of the quad integer
48.Fa j .
49.Sh SEE ALSO
50.Xr abs 3 ,
51.Xr cabs 3 ,
52.Xr floor 3 ,
53.Xr labs 3 ,
54.Xr math 3
55.Sh BUGS
56The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/qabs.c b/src/lib/libc/stdlib/qabs.c
new file mode 100644
index 0000000000..4c561b3351
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: qabs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36quad_t
37qabs(quad_t j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
new file mode 100644
index 0000000000..5f17ec17d4
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -0,0 +1,60 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qdiv.3,v 1.6 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt QDIV 3
36.Os
37.Sh NAME
38.Nm qdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft qdiv_t
43.Fn qdiv "quad_t num" "quad_t denom"
44.Sh DESCRIPTION
45The
46.Fn qdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li qdiv_t
51that contains two
52.Li quad integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr ldiv 3 ,
60.Xr math 3
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
new file mode 100644
index 0000000000..8147ee89a6
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: qdiv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* qdiv_t */
38
39qdiv_t
40qdiv(quad_t num, quad_t denom)
41{
42 qdiv_t r;
43
44 /* see div.c for comments */
45
46 r.quot = num / denom;
47 r.rem = num % denom;
48 if (num >= 0 && r.rem < 0) {
49 r.quot++;
50 r.rem -= denom;
51 }
52 return (r);
53}
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
new file mode 100644
index 0000000000..668ea90243
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.3
@@ -0,0 +1,233 @@
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.14 2003/10/01 08:11:58 jmc Exp $
33.\"
34.Dd June 4, 1993
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.Fd #include <stdlib.h>
44.Ft void
45.Fn qsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
46.Ft int
47.Fn heapsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
48.Ft int
49.Fn mergesort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
50.Sh DESCRIPTION
51The
52.Fn qsort
53function is a modified partition-exchange sort, or quicksort.
54The
55.Fn heapsort
56function is a modified selection sort.
57The
58.Fn mergesort
59function is a modified merge sort with exponential search
60intended for sorting data with pre-existing order.
61.Pp
62The
63.Fn qsort
64and
65.Fn heapsort
66functions sort an array of
67.Fa nmemb
68objects, the initial member of which is pointed to by
69.Fa base .
70The size of each object is specified by
71.Fa size .
72.Fn mergesort
73behaves similarly, but
74.Em requires
75that
76.Fa size
77be greater than
78.Dq "sizeof(void *) / 2" .
79.Pp
80The contents of the array
81.Fa base
82are sorted in ascending order according to
83a comparison function pointed to by
84.Fa compar ,
85which requires two arguments pointing to the objects being
86compared.
87.Pp
88The comparison function must return an integer less than, equal to, or
89greater than zero if the first argument is considered to be respectively
90less than, equal to, or greater than the second.
91.Pp
92The functions
93.Fn qsort
94and
95.Fn heapsort
96are
97.Em not
98stable, that is, if two members compare as equal, their order in
99the sorted array is undefined.
100The function
101.Fn mergesort
102is stable.
103.Pp
104The
105.Fn qsort
106function is an implementation of C.A.R. Hoare's
107.Dq quicksort
108algorithm,
109a variant of partition-exchange sorting; in particular, see D.E. Knuth's
110Algorithm Q.
111.Fn qsort
112takes O N lg N average time.
113This implementation uses median selection to avoid its
114O N**2 worst-case behavior.
115.Pp
116The
117.Fn heapsort
118function is an implementation of J.W.J. William's
119.Dq heapsort
120algorithm,
121a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
122.Fn heapsort
123takes O N lg N worst-case time.
124This implementation of
125.Fn heapsort
126is implemented without recursive function calls.
127.Pp
128The function
129.Fn mergesort
130requires additional memory of size
131.Fa nmemb *
132.Fa size
133bytes; it should be used only when space is not at a premium.
134.Fn mergesort
135is optimized for data with pre-existing order; its worst case
136time is O N lg N; its best case is O N.
137.Pp
138Normally,
139.Fn qsort
140is faster than
141.Fn mergesort ,
142which is faster than
143.Fn heapsort .
144Memory availability and pre-existing order in the data can make this untrue.
145.Sh RETURN VALUES
146The
147.Fn qsort
148function returns no value.
149.Pp
150Upon successful completion,
151.Fn heapsort
152and
153.Fn mergesort
154return 0.
155Otherwise, they return \-1 and the global variable
156.Va errno
157is set to indicate the error.
158.Sh ERRORS
159The
160.Fn heapsort
161and
162.Fn mergesort
163functions succeed unless:
164.Bl -tag -width Er
165.It Bq Er EINVAL
166The
167.Fa size
168argument is zero, or the
169.Fa size
170argument to
171.Fn mergesort
172is less than
173.Dq "sizeof(void *) / 2" .
174.It Bq Er ENOMEM
175.Fn heapsort
176or
177.Fn mergesort
178were unable to allocate memory.
179.El
180.Sh SEE ALSO
181.Xr sort 1 ,
182.Xr radixsort 3
183.Rs
184.%A Hoare, C.A.R.
185.%D 1962
186.%T "Quicksort"
187.%J "The Computer Journal"
188.%V 5:1
189.%P pp. 10-15
190.Re
191.Rs
192.%A Williams, J.W.J
193.%D 1964
194.%T "Heapsort"
195.%J "Communications of the ACM"
196.%V 7:1
197.%P pp. 347\-348
198.Re
199.Rs
200.%A Knuth, D.E.
201.%D 1968
202.%B "The Art of Computer Programming"
203.%V Vol. 3
204.%T "Sorting and Searching"
205.%P pp. 114\-123, 145\-149
206.Re
207.Rs
208.%A McIlroy, P.M.
209.%T "Optimistic Sorting and Information Theoretic Complexity"
210.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
211.%P pp. 467\-464
212.%D January 1993
213.Re
214.Rs
215.%A Bentley, J.L.
216.%A McIlroy, M.D.
217.%T "Engineering a Sort Function"
218.%J "Software \- Practice and Experience"
219.%V Vol. 23(11)
220.%P pp. 1249\-1265
221.%D November 1993
222.Re
223.Sh STANDARDS
224Previous versions of
225.Fn qsort
226did not permit the comparison routine itself to call
227.Fn qsort .
228This is no longer true.
229.Pp
230The
231.Fn qsort
232function conforms to
233.St -ansiC .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
new file mode 100644
index 0000000000..154c51a86c
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.c
@@ -0,0 +1,164 @@
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: qsort.c,v 1.9 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <stdlib.h>
36
37static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
38static __inline void swapfunc(char *, char *, int, int);
39
40#define min(a, b) (a) < (b) ? a : b
41
42/*
43 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
44 */
45#define swapcode(TYPE, parmi, parmj, n) { \
46 long i = (n) / sizeof (TYPE); \
47 TYPE *pi = (TYPE *) (parmi); \
48 TYPE *pj = (TYPE *) (parmj); \
49 do { \
50 TYPE t = *pi; \
51 *pi++ = *pj; \
52 *pj++ = t; \
53 } while (--i > 0); \
54}
55
56#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
57 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
58
59static __inline void
60swapfunc(char *a, char *b, int n, int swaptype)
61{
62 if (swaptype <= 1)
63 swapcode(long, a, b, n)
64 else
65 swapcode(char, a, b, n)
66}
67
68#define swap(a, b) \
69 if (swaptype == 0) { \
70 long t = *(long *)(a); \
71 *(long *)(a) = *(long *)(b); \
72 *(long *)(b) = t; \
73 } else \
74 swapfunc(a, b, es, swaptype)
75
76#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
77
78static __inline char *
79med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
80{
81 return cmp(a, b) < 0 ?
82 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
83 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
84}
85
86void
87qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
88{
89 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
90 int d, r, swaptype, swap_cnt;
91 char *a = aa;
92
93loop: SWAPINIT(a, es);
94 swap_cnt = 0;
95 if (n < 7) {
96 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
97 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
98 pl -= es)
99 swap(pl, pl - es);
100 return;
101 }
102 pm = (char *)a + (n / 2) * es;
103 if (n > 7) {
104 pl = (char *)a;
105 pn = (char *)a + (n - 1) * es;
106 if (n > 40) {
107 d = (n / 8) * es;
108 pl = med3(pl, pl + d, pl + 2 * d, cmp);
109 pm = med3(pm - d, pm, pm + d, cmp);
110 pn = med3(pn - 2 * d, pn - d, pn, cmp);
111 }
112 pm = med3(pl, pm, pn, cmp);
113 }
114 swap(a, pm);
115 pa = pb = (char *)a + es;
116
117 pc = pd = (char *)a + (n - 1) * es;
118 for (;;) {
119 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
120 if (r == 0) {
121 swap_cnt = 1;
122 swap(pa, pb);
123 pa += es;
124 }
125 pb += es;
126 }
127 while (pb <= pc && (r = cmp(pc, a)) >= 0) {
128 if (r == 0) {
129 swap_cnt = 1;
130 swap(pc, pd);
131 pd -= es;
132 }
133 pc -= es;
134 }
135 if (pb > pc)
136 break;
137 swap(pb, pc);
138 swap_cnt = 1;
139 pb += es;
140 pc -= es;
141 }
142 if (swap_cnt == 0) { /* Switch to insertion sort */
143 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
144 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
145 pl -= es)
146 swap(pl, pl - es);
147 return;
148 }
149
150 pn = (char *)a + n * es;
151 r = min(pa - (char *)a, pb - pa);
152 vecswap(a, pb - r, r);
153 r = min(pd - pc, pn - pd - es);
154 vecswap(pb, pn - r, r);
155 if ((r = pb - pa) > es)
156 qsort(a, r / es, es, cmp);
157 if ((r = pd - pc) > es) {
158 /* Iterate rather than recurse to save stack space */
159 a = pn - r;
160 n = r / es;
161 goto loop;
162 }
163/* qsort(pn - r, r / es, es, cmp);*/
164}
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
new file mode 100644
index 0000000000..028837d4d1
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -0,0 +1,155 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: radixsort.3,v 1.9 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd January 27, 1994
31.Dt RADIXSORT 3
32.Os
33.Sh NAME
34.Nm radixsort ,
35.Nm sradixsort
36.Nd radix sort
37.Sh SYNOPSIS
38.Fd #include <limits.h>
39.Fd #include <stdlib.h>
40.Ft int
41.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
42.Ft int
43.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
44.Sh DESCRIPTION
45The
46.Fn radixsort
47and
48.Fn sradixsort
49functions are implementations of radix sort.
50.Pp
51These functions sort an array of
52.Fa nmemb
53pointers to byte strings.
54The initial member is referenced by
55.Fa base .
56The byte strings may contain any values; the end of each string
57is denoted by the user-specified value
58.Fa endbyte .
59.Pp
60Applications may specify a sort order by providing the
61.Fa table
62argument.
63If non-null,
64.Fa table
65must reference an array of
66.Dv UCHAR_MAX
67+ 1 bytes which contains the sort weight of each possible byte value.
68The end-of-string byte must have a sort weight of 0 or 255
69(for sorting in reverse order).
70More than one byte may have the same sort weight.
71The
72.Fa table
73argument is useful for applications which wish to sort different characters
74equally, for example, providing a table with the same weights
75for A-Z as for a-z will result in a case-insensitive sort.
76If
77.Fa table
78is
79.Dv NULL ,
80the contents of the array are sorted in ascending order according to the
81.Tn ASCII
82order of the byte strings they reference and
83.Fa endbyte
84has a sorting weight of 0.
85.Pp
86The
87.Fn sradixsort
88function is stable; that is, if two elements compare as equal, their
89order in the sorted array is unchanged.
90The
91.Fn sradixsort
92function uses additional memory sufficient to hold
93.Fa nmemb
94pointers.
95.Pp
96The
97.Fn radixsort
98function is not stable, but uses no additional memory.
99.Pp
100These functions are variants of most-significant-byte radix sorting; in
101particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
102They take linear time relative to the number of bytes in the strings.
103.Sh RETURN VALUES
104Upon successful completion 0 is returned.
105Otherwise, \-1 is returned and the global variable
106.Va errno
107is set to indicate the error.
108.Sh ERRORS
109.Bl -tag -width Er
110.It Bq Er EINVAL
111The value of the
112.Fa endbyte
113element of
114.Fa table
115is not 0 or 255.
116.El
117.Pp
118Additionally, the
119.Fn sradixsort
120function may fail and set
121.Va errno
122for any of the errors specified for the library routine
123.Xr malloc 3 .
124.Sh SEE ALSO
125.Xr sort 1 ,
126.Xr qsort 3
127.Rs
128.%A Knuth, D.E.
129.%D 1968
130.%B "The Art of Computer Programming"
131.%T "Sorting and Searching"
132.%V Vol. 3
133.%P pp. 170-178
134.Re
135.Rs
136.%A Paige, R.
137.%D 1987
138.%T "Three Partition Refinement Algorithms"
139.%J "SIAM J. Comput."
140.%V Vol. 16
141.%N No. 6
142.Re
143.Rs
144.%A McIlroy, P.
145.%D 1993
146.%B "Engineering Radix Sort"
147.%T "Computing Systems"
148.%V Vol. 6:1
149.%P pp. 5-27
150.Re
151.Sh HISTORY
152The
153.Fn radixsort
154function first appeared in
155.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
new file mode 100644
index 0000000000..96392ea73a
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,297 @@
1/*-
2 * Copyright (c) 1990, 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 * Peter McIlroy and by Dan Bernstein at New York University,
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: radixsort.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37/*
38 * Radixsort routines.
39 *
40 * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
41 * Use radixsort(a, n, trace, endchar) for this case.
42 *
43 * For stable sorting (using N extra pointers) use sradixsort(), which calls
44 * r_sort_b().
45 *
46 * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
47 * "Engineering Radix Sort".
48 */
49
50#include <sys/types.h>
51#include <stdlib.h>
52#include <errno.h>
53
54typedef struct {
55 const u_char **sa;
56 int sn, si;
57} stack;
58
59static __inline void simplesort
60(const u_char **, int, int, const u_char *, u_int);
61static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
62static void r_sort_b(const u_char **,
63 const u_char **, int, int, const u_char *, u_int);
64
65#define THRESHOLD 20 /* Divert to simplesort(). */
66#define SIZE 512 /* Default stack size. */
67
68#define SETUP { \
69 if (tab == NULL) { \
70 tr = tr0; \
71 for (c = 0; c < endch; c++) \
72 tr0[c] = c + 1; \
73 tr0[c] = 0; \
74 for (c++; c < 256; c++) \
75 tr0[c] = c; \
76 endch = 0; \
77 } else { \
78 endch = tab[endch]; \
79 tr = tab; \
80 if (endch != 0 && endch != 255) { \
81 errno = EINVAL; \
82 return (-1); \
83 } \
84 } \
85}
86
87int
88radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
89{
90 const u_char *tr;
91 int c;
92 u_char tr0[256];
93
94 SETUP;
95 r_sort_a(a, n, 0, tr, endch);
96 return (0);
97}
98
99int
100sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
101{
102 const u_char *tr, **ta;
103 int c;
104 u_char tr0[256];
105
106 SETUP;
107 if (n < THRESHOLD)
108 simplesort(a, n, 0, tr, endch);
109 else {
110 if ((ta = malloc(n * sizeof(a))) == NULL)
111 return (-1);
112 r_sort_b(a, ta, n, 0, tr, endch);
113 free(ta);
114 }
115 return (0);
116}
117
118#define empty(s) (s >= sp)
119#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
120#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
121#define swap(a, b, t) t = a, a = b, b = t
122
123/* Unstable, in-place sort. */
124void
125r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
126{
127 static int count[256], nc, bmin;
128 int c;
129 const u_char **ak, *r;
130 stack s[SIZE], *sp, *sp0, *sp1, temp;
131 int *cp, bigc;
132 const u_char **an, *t, **aj, **top[256];
133
134 /* Set up stack. */
135 sp = s;
136 push(a, n, i);
137 while (!empty(s)) {
138 pop(a, n, i);
139 if (n < THRESHOLD) {
140 simplesort(a, n, i, tr, endch);
141 continue;
142 }
143 an = a + n;
144
145 /* Make character histogram. */
146 if (nc == 0) {
147 bmin = 255; /* First occupied bin, excluding eos. */
148 for (ak = a; ak < an;) {
149 c = tr[(*ak++)[i]];
150 if (++count[c] == 1 && c != endch) {
151 if (c < bmin)
152 bmin = c;
153 nc++;
154 }
155 }
156 if (sp + nc > s + SIZE) { /* Get more stack. */
157 r_sort_a(a, n, i, tr, endch);
158 continue;
159 }
160 }
161
162 /*
163 * Set top[]; push incompletely sorted bins onto stack.
164 * top[] = pointers to last out-of-place element in bins.
165 * count[] = counts of elements in bins.
166 * Before permuting: top[c-1] + count[c] = top[c];
167 * during deal: top[c] counts down to top[c-1].
168 */
169 sp0 = sp1 = sp; /* Stack position of biggest bin. */
170 bigc = 2; /* Size of biggest bin. */
171 if (endch == 0) /* Special case: set top[eos]. */
172 top[0] = ak = a + count[0];
173 else {
174 ak = a;
175 top[255] = an;
176 }
177 for (cp = count + bmin; nc > 0; cp++) {
178 while (*cp == 0) /* Find next non-empty pile. */
179 cp++;
180 if (*cp > 1) {
181 if (*cp > bigc) {
182 bigc = *cp;
183 sp1 = sp;
184 }
185 push(ak, *cp, i+1);
186 }
187 top[cp-count] = ak += *cp;
188 nc--;
189 }
190 swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
191
192 /*
193 * Permute misplacements home. Already home: everything
194 * before aj, and in bin[c], items from top[c] on.
195 * Inner loop:
196 * r = next element to put in place;
197 * ak = top[r[i]] = location to put the next element.
198 * aj = bottom of 1st disordered bin.
199 * Outer loop:
200 * Once the 1st disordered bin is done, ie. aj >= ak,
201 * aj<-aj + count[c] connects the bins in a linked list;
202 * reset count[c].
203 */
204 for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
205 for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
206 swap(*ak, r, t);
207 }
208}
209
210/* Stable sort, requiring additional memory. */
211void
212r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
213 u_int endch)
214{
215 static int count[256], nc, bmin;
216 int c;
217 const u_char **ak, **ai;
218 stack s[512], *sp, *sp0, *sp1, temp;
219 const u_char **top[256];
220 int *cp, bigc;
221
222 sp = s;
223 push(a, n, i);
224 while (!empty(s)) {
225 pop(a, n, i);
226 if (n < THRESHOLD) {
227 simplesort(a, n, i, tr, endch);
228 continue;
229 }
230
231 if (nc == 0) {
232 bmin = 255;
233 for (ak = a + n; --ak >= a;) {
234 c = tr[(*ak)[i]];
235 if (++count[c] == 1 && c != endch) {
236 if (c < bmin)
237 bmin = c;
238 nc++;
239 }
240 }
241 if (sp + nc > s + SIZE) {
242 r_sort_b(a, ta, n, i, tr, endch);
243 continue;
244 }
245 }
246
247 sp0 = sp1 = sp;
248 bigc = 2;
249 if (endch == 0) {
250 top[0] = ak = a + count[0];
251 count[0] = 0;
252 } else {
253 ak = a;
254 top[255] = a + n;
255 count[255] = 0;
256 }
257 for (cp = count + bmin; nc > 0; cp++) {
258 while (*cp == 0)
259 cp++;
260 if ((c = *cp) > 1) {
261 if (c > bigc) {
262 bigc = c;
263 sp1 = sp;
264 }
265 push(ak, c, i+1);
266 }
267 top[cp-count] = ak += c;
268 *cp = 0; /* Reset count[]. */
269 nc--;
270 }
271 swap(*sp0, *sp1, temp);
272
273 for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
274 *--ak = *--ai;
275 for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
276 *--top[tr[(*ak)[i]]] = *ak;
277 }
278}
279
280static __inline void
281simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
282 /* insertion sort */
283{
284 u_char ch;
285 const u_char **ak, **ai, *s, *t;
286
287 for (ak = a+1; --n >= 1; ak++)
288 for (ai = ak; ai > a; ai--) {
289 for (s = ai[0] + b, t = ai[-1] + b;
290 (ch = tr[*s]) != endch; s++, t++)
291 if (ch != tr[*t])
292 break;
293 if (ch >= tr[*t])
294 break;
295 swap(ai[0], ai[-1], s);
296 }
297}
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
new file mode 100644
index 0000000000..0d9c52a3b9
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.3
@@ -0,0 +1,98 @@
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.9 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt RAND 3
36.Os
37.Sh NAME
38.Nm rand ,
39.Nm srand
40.Nd bad random number generator
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft void
44.Fn srand "unsigned int seed"
45.Ft int
46.Fn rand void
47.Ft int
48.Fn rand_r "unsigned int *seed"
49.Sh DESCRIPTION
50.Bf -symbolic
51These interfaces are obsoleted by
52.Xr random 3 .
53.Ef
54.Pp
55The
56.Fn rand
57function computes a sequence of pseudo-random integers in the range
58of 0 to
59.Dv RAND_MAX
60(as defined by the header file
61.Aq Pa stdlib.h ) .
62.Pp
63The
64.Fn srand
65function sets its argument as the seed for a new sequence of
66pseudo-random numbers to be returned by
67.Fn rand .
68These sequences are repeatable by calling
69.Fn srand
70with the same seed value.
71.Pp
72If no seed value is provided, the functions are automatically
73seeded with a value of 1.
74.Pp
75The
76.Fn rand_r
77is a thread-safe version of
78.Fn rand .
79Storage for the seed must be provided through the
80.Fa seed
81argument, and needs to have been initialized by the caller.
82.Sh SEE ALSO
83.Xr arc4random 3 ,
84.Xr rand48 3 ,
85.Xr random 3
86.Sh STANDARDS
87The
88.Fn rand
89and
90.Fn srand
91functions conform to
92.St -ansiC .
93.Pp
94The
95.Fn rand_r
96function conforms to ISO/IEC 9945-1 ANSI/IEEE
97.Pq Dq Tn POSIX
98Std 1003.1c Draft 10.
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
new file mode 100644
index 0000000000..6b27ad46d3
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.c
@@ -0,0 +1,56 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: rand.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <stdlib.h>
36
37static u_int next = 1;
38
39int
40rand_r(u_int *seed)
41{
42 *seed = *seed * 1103515245 + 12345;
43 return (*seed % ((u_int)RAND_MAX + 1));
44}
45
46int
47rand(void)
48{
49 return (rand_r(&next));
50}
51
52void
53srand(u_int seed)
54{
55 next = seed;
56}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
new file mode 100644
index 0000000000..78cd0a7cd5
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.3
@@ -0,0 +1,165 @@
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.10 2003/06/01 19:27:27 jmc Exp $
13.\"
14.Dd October 8, 1993
15.Dt RAND48 3
16.Os
17.Sh NAME
18.Nm drand48 ,
19.Nm erand48 ,
20.Nm lrand48 ,
21.Nm nrand48 ,
22.Nm mrand48 ,
23.Nm jrand48 ,
24.Nm srand48 ,
25.Nm seed48 ,
26.Nm lcong48
27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS
29.Fd #include <stdlib.h>
30.Ft double
31.Fn drand48 void
32.Ft double
33.Fn erand48 "unsigned short xseed[3]"
34.Ft long
35.Fn lrand48 void
36.Ft long
37.Fn nrand48 "unsigned short xseed[3]"
38.Ft long
39.Fn mrand48 void
40.Ft long
41.Fn jrand48 "unsigned short xseed[3]"
42.Ft void
43.Fn srand48 "long seed"
44.Ft "unsigned short *"
45.Fn seed48 "unsigned short xseed[3]"
46.Ft void
47.Fn lcong48 "unsigned short p[7]"
48.Sh DESCRIPTION
49The
50.Fn rand48
51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size.
53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m
55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
59r(n) is called the seed of the random number generator.
60.Pp
61For all the six generator routines described next, the first
62computational step is to perform a single iteration of the algorithm.
63.Pp
64.Fn drand48
65and
66.Fn erand48
67return values of type double.
68The full 48 bits of r(n+1) are
69loaded into the mantissa of the returned value, with the exponent set
70such that the values produced lie in the interval [0.0, 1.0].
71.Pp
72.Fn lrand48
73and
74.Fn nrand48
75return values of type long in the range
76[0, 2**31-1].
77The high-order (31) bits of
78r(n+1) are loaded into the lower bits of the returned value, with
79the topmost (sign) bit set to zero.
80.Pp
81.Fn mrand48
82and
83.Fn jrand48
84return values of type long in the range
85[-2**31, 2**31-1].
86The high-order (32) bits of r(n+1) are loaded into the returned value.
87.Pp
88.Fn drand48 ,
89.Fn lrand48 ,
90and
91.Fn mrand48
92use an internal buffer to store r(n).
93For these functions
94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
95.Pp
96On the other hand,
97.Fn erand48 ,
98.Fn nrand48 ,
99and
100.Fn jrand48
101use a user-supplied buffer to store the seed r(n),
102which consists of an array of 3 shorts, where the zeroth member
103holds the least significant bits.
104.Pp
105All functions share the same multiplicand and addend.
106.Pp
107.Fn srand48
108is used to initialize the internal buffer r(n) of
109.Fn drand48 ,
110.Fn lrand48 ,
111and
112.Fn mrand48
113such that the 32 bits of the seed value are copied into the upper 32 bits
114of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
115Additionally, the constant multiplicand and addend of the algorithm are
116reset to the default values given above.
117.Pp
118.Fn seed48
119also initializes the internal buffer r(n) of
120.Fn drand48 ,
121.Fn lrand48 ,
122and
123.Fn mrand48 ,
124but here all 48 bits of the seed can be specified in an array of 3 shorts,
125where the zeroth member specifies the lowest bits.
126Again, the constant multiplicand and addend of the algorithm are
127reset to the default values given above.
128.Fn seed48
129returns a pointer to an array of 3 shorts which contains the old seed.
130This array is statically allocated, so its contents are lost after
131each new call to
132.Fn seed48 .
133.Pp
134Finally,
135.Fn lcong48
136allows full control over the multiplicand and addend used in
137.Fn drand48 ,
138.Fn erand48 ,
139.Fn lrand48 ,
140.Fn nrand48 ,
141.Fn mrand48 ,
142and
143.Fn jrand48 ,
144and the seed used in
145.Fn drand48 ,
146.Fn lrand48 ,
147and
148.Fn mrand48 .
149An array of 7 shorts is passed as parameter; the first three shorts are
150used to initialize the seed; the second three are used to initialize the
151multiplicand; and the last short is used to initialize the addend.
152It is thus not possible to use values greater than 0xffff as the addend.
153.Pp
154Note that all three methods of seeding the random number generator
155always also set the multiplicand and addend for any of the six
156generator calls.
157.Pp
158For a more powerful random number generator, see
159.Xr random 3 .
160.Sh SEE ALSO
161.Xr arc4random 3 ,
162.Xr rand 3 ,
163.Xr random 3
164.Sh AUTHORS
165Martin Birgmeier
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
new file mode 100644
index 0000000000..afa49f65f3
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
14 */
15
16#ifndef _RAND48_H_
17#define _RAND48_H_
18
19#include <math.h>
20#include <stdlib.h>
21
22void __dorand48(unsigned short[3]);
23
24#define RAND48_SEED_0 (0x330e)
25#define RAND48_SEED_1 (0xabcd)
26#define RAND48_SEED_2 (0x1234)
27#define RAND48_MULT_0 (0xe66d)
28#define RAND48_MULT_1 (0xdeec)
29#define RAND48_MULT_2 (0x0005)
30#define RAND48_ADD (0x000b)
31
32#endif /* _RAND48_H_ */
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
new file mode 100644
index 0000000000..f43f06420d
--- /dev/null
+++ b/src/lib/libc/stdlib/random.3
@@ -0,0 +1,186 @@
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.17 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd April 19, 1991
31.Dt RANDOM 3
32.Os
33.Sh NAME
34.Nm random ,
35.Nm srandom ,
36.Nm srandomdev ,
37.Nm initstate ,
38.Nm setstate
39.Nd better random number generator; routines for changing generators
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft long
43.Fn random void
44.Ft void
45.Fn srandom "unsigned int seed"
46.Ft void
47.Fn srandomdev void
48.Ft char *
49.Fn initstate "unsigned int seed" "char *state" "size_t n"
50.Ft char *
51.Fn setstate "const char *state"
52.Sh DESCRIPTION
53The
54.Fn random
55function uses a non-linear additive feedback random number generator employing
56a default table of size 31 long integers to return successive pseudo-random
57numbers in the range from 0 to (2**31)\-1.
58The period of this random number generator is very large, approximately
5916*((2**31)\-1).
60.Pp
61The
62.Fn random
63and
64.Fn srandom
65functions have (almost) the same calling sequence and initialization
66properties as
67.Xr rand 3 Ns / Ns Xr srand 3 .
68The difference is that
69.Xr rand
70produces a much less random sequence \(em in fact, the low dozen bits
71generated by rand go through a cyclic pattern.
72All the bits generated by
73.Fn random
74are usable.
75For example,
76.Sq Li random()&01
77will produce a random binary
78value.
79.Pp
80Like
81.Xr rand 3 ,
82.Fn random
83will by default produce a sequence of numbers that can be duplicated
84by calling
85.Fn srandom
86with
87.Ql 1
88as the seed.
89.Pp
90The
91.Fn srandomdev
92routine initializes a state array using the
93.Xr arandom 4
94random number device which returns good random numbers,
95suitable for cryptographic use.
96Note that this particular seeding procedure can generate
97states which are impossible to reproduce by calling
98.Fn srandom
99with any value, since the succeeding terms in the
100state buffer are no longer derived from the LC algorithm applied to
101a fixed seed.
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
150With 256 bytes of state information, the period of the random number
151generator is greater than 2**69
152which should be sufficient for most purposes.
153.Sh DIAGNOSTICS
154If
155.Fn initstate
156is called with less than 8 bytes of state information, or if
157.Fn setstate
158detects that the state information has been garbled, error
159messages are printed on the standard error output.
160.Sh SEE ALSO
161.Xr arc4random 3 ,
162.Xr drand48 3 ,
163.Xr rand 3 ,
164.Xr random 4
165.Sh STANDARDS
166The
167.Fn random ,
168.Fn srandom ,
169.Fn initstate ,
170and
171.Fn setstate
172functions conform to
173.St -xpg4.2 .
174.Pp
175The
176.Fn srandomdev
177function is an extension.
178.Sh HISTORY
179These
180functions appeared in
181.Bx 4.2 .
182.Sh AUTHORS
183.An Earl T. Cohen
184.Sh BUGS
185About 2/3 the speed of
186.Xr rand 3 .
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
new file mode 100644
index 0000000000..4ca8735e75
--- /dev/null
+++ b/src/lib/libc/stdlib/random.c
@@ -0,0 +1,425 @@
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: random.c,v 1.13 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <sys/sysctl.h>
36#include <sys/time.h>
37#include <fcntl.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <unistd.h>
41
42/*
43 * random.c:
44 *
45 * An improved random number generation package. In addition to the standard
46 * rand()/srand() like interface, this package also has a special state info
47 * interface. The initstate() routine is called with a seed, an array of
48 * bytes, and a count of how many bytes are being passed in; this array is
49 * then initialized to contain information for random number generation with
50 * that much state information. Good sizes for the amount of state
51 * information are 32, 64, 128, and 256 bytes. The state can be switched by
52 * calling the setstate() routine with the same array as was initiallized
53 * with initstate(). By default, the package runs with 128 bytes of state
54 * information and generates far better random numbers than a linear
55 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used.
57 *
58 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details).
65 *
66 * The random number generation technique is a linear feedback shift register
67 * approach, employing trinomials (since there are fewer terms to sum up that
68 * way). In this approach, the least significant bit of all the numbers in
69 * the state table will act as a linear feedback shift register, and will
70 * have period 2^deg - 1 (where deg is the degree of the polynomial being
71 * used, assuming that the polynomial is irreducible and primitive). The
72 * higher order bits will have longer periods, since their values are also
73 * influenced by pseudo-random carries out of the lower bits. The total
74 * period of the generator is approximately deg*(2**deg - 1); thus doubling
75 * the amount of state information has a vast influence on the period of the
76 * generator. Note: the deg*(2**deg - 1) is an approximation only good for
77 * large deg, when the period of the shift register is the dominant factor.
78 * With deg equal to seven, the period is actually much longer than the
79 * 7*(2**7 - 1) predicted by this formula.
80 */
81
82/*
83 * For each of the currently supported random number generators, we have a
84 * break value on the amount of state information (you need at least this
85 * many bytes of state info to support this random number generator), a degree
86 * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
87 * the separation between the two lower order coefficients of the trinomial.
88 */
89#define TYPE_0 0 /* linear congruential */
90#define BREAK_0 8
91#define DEG_0 0
92#define SEP_0 0
93
94#define TYPE_1 1 /* x**7 + x**3 + 1 */
95#define BREAK_1 32
96#define DEG_1 7
97#define SEP_1 3
98
99#define TYPE_2 2 /* x**15 + x + 1 */
100#define BREAK_2 64
101#define DEG_2 15
102#define SEP_2 1
103
104#define TYPE_3 3 /* x**31 + x**3 + 1 */
105#define BREAK_3 128
106#define DEG_3 31
107#define SEP_3 3
108
109#define TYPE_4 4 /* x**63 + x + 1 */
110#define BREAK_4 256
111#define DEG_4 63
112#define SEP_4 1
113
114/*
115 * Array versions of the above information to make code run faster --
116 * relies on fact that TYPE_i == i.
117 */
118#define MAX_TYPES 5 /* max number of types above */
119
120static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
121static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
122
123/*
124 * Initially, everything is set up as if from:
125 *
126 * initstate(1, &randtbl, 128);
127 *
128 * Note that this initialization takes advantage of the fact that srandom()
129 * advances the front and rear pointers 10*rand_deg times, and hence the
130 * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
131 * element of the state information, which contains info about the current
132 * position of the rear pointer is just
133 *
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */
136
137static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3,
139 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0xf3bec5da,
145};
146
147/*
148 * fptr and rptr are two pointers into the state info, a front and a rear
149 * pointer. These two pointers are always rand_sep places aparts, as they
150 * cycle cyclically through the state information. (Yes, this does mean we
151 * could get away with just one pointer, but the code for random() is more
152 * efficient this way). The pointers are left positioned as they would be
153 * from the call
154 *
155 * initstate(1, randtbl, 128);
156 *
157 * (The position of the rear pointer, rptr, is really 0 (as explained above
158 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below).
160 */
161static int32_t *fptr = &randtbl[SEP_3 + 1];
162static int32_t *rptr = &randtbl[1];
163
164/*
165 * The following things are the pointer to the state information table, the
166 * type of the current generator, the degree of the current polynomial being
167 * used, and the separation between the two pointers. Note that for efficiency
168 * of random(), we remember the first location of the state information, not
169 * the zeroeth. Hence it is valid to access state[-1], which is used to
170 * store the type of the R.N.G. Also, we remember the last location, since
171 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped.
173 */
174static int32_t *state = &randtbl[1];
175static int32_t *end_ptr = &randtbl[DEG_3 + 1];
176static int rand_type = TYPE_3;
177static int rand_deg = DEG_3;
178static int rand_sep = SEP_3;
179
180/*
181 * srandom:
182 *
183 * Initialize the random number generator based on the given seed. If the
184 * type is the trivial no-state-information type, just remember the seed.
185 * Otherwise, initializes state[] based on the given "seed" via a linear
186 * congruential generator. Then, the pointers are set to known locations
187 * that are exactly rand_sep places apart. Lastly, it cycles the state
188 * information a given number of times to get rid of any initial dependencies
189 * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
190 * for default usage relies on values produced by this routine.
191 */
192void
193srandom(unsigned int x)
194{
195 int i;
196 int32_t test;
197 div_t val;
198
199 if (rand_type == TYPE_0)
200 state[0] = x;
201 else {
202 state[0] = x;
203 for (i = 1; i < rand_deg; i++) {
204 /*
205 * Implement the following, without overflowing 31 bits:
206 *
207 * state[i] = (16807 * state[i - 1]) % 2147483647;
208 *
209 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
210 */
211 val = div(state[i-1], 127773);
212 test = 16807 * val.rem - 2836 * val.quot;
213 state[i] = test + (test < 0 ? 2147483647 : 0);
214 }
215 fptr = &state[rand_sep];
216 rptr = &state[0];
217 for (i = 0; i < 10 * rand_deg; i++)
218 (void)random();
219 }
220}
221
222/*
223 * srandomdev:
224 *
225 * Many programs choose the seed value in a totally predictable manner.
226 * This often causes problems. We seed the generator using the much more
227 * secure arandom(4) interface. Note that this particular seeding
228 * procedure can generate states which are impossible to reproduce by
229 * calling srandom() with any value, since the succeeding terms in the
230 * state buffer are no longer derived from the LC algorithm applied to
231 * a fixed seed.
232 */
233void
234srandomdev(void)
235{
236 int fd, i, mib[2], n;
237 size_t len;
238
239 if (rand_type == TYPE_0)
240 len = sizeof(state[0]);
241 else
242 len = rand_deg * sizeof(state[0]);
243
244 /*
245 * To get seed data, first try reading from /dev/arandom.
246 * If that fails, try the KERN_ARND sysctl() (one int at a time).
247 * As a last resort, call srandom().
248 */
249 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
250 read(fd, (void *) state, len) == (ssize_t) len) {
251 close(fd);
252 } else {
253 if (fd != -1)
254 close(fd);
255 mib[0] = CTL_KERN;
256 mib[1] = KERN_ARND;
257 n = len / sizeof(int);
258 len = sizeof(int);
259 for (i = 0; i < n; i++) {
260 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
261 NULL, 0) == -1)
262 break;
263 }
264 if (i != n) {
265 struct timeval tv;
266 u_int junk;
267
268 /* XXX - this could be better */
269 gettimeofday(&tv, NULL);
270 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
271 return;
272 }
273 }
274
275 if (rand_type != TYPE_0) {
276 fptr = &state[rand_sep];
277 rptr = &state[0];
278 }
279}
280
281/*
282 * initstate:
283 *
284 * Initialize the state information in the given array of n bytes for future
285 * random number generation. Based on the number of bytes we are given, and
286 * the break values for the different R.N.G.'s, we choose the best (largest)
287 * one we can and set things up for it. srandom() is then called to
288 * initialize the state information.
289 *
290 * Note that on return from srandom(), we set state[-1] to be the type
291 * multiplexed with the current value of the rear pointer; this is so
292 * successive calls to initstate() won't lose this information and will be
293 * able to restart with setstate().
294 *
295 * Note: the first thing we do is save the current state, if any, just like
296 * setstate() so that it doesn't matter when initstate is called.
297 *
298 * Returns a pointer to the old state.
299 */
300char *
301initstate(u_int seed, char *arg_state, size_t n)
302{
303 char *ostate = (char *)(&state[-1]);
304
305 if (rand_type == TYPE_0)
306 state[-1] = rand_type;
307 else
308 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
309 if (n < BREAK_0)
310 return(NULL);
311 if (n < BREAK_1) {
312 rand_type = TYPE_0;
313 rand_deg = DEG_0;
314 rand_sep = SEP_0;
315 } else if (n < BREAK_2) {
316 rand_type = TYPE_1;
317 rand_deg = DEG_1;
318 rand_sep = SEP_1;
319 } else if (n < BREAK_3) {
320 rand_type = TYPE_2;
321 rand_deg = DEG_2;
322 rand_sep = SEP_2;
323 } else if (n < BREAK_4) {
324 rand_type = TYPE_3;
325 rand_deg = DEG_3;
326 rand_sep = SEP_3;
327 } else {
328 rand_type = TYPE_4;
329 rand_deg = DEG_4;
330 rand_sep = SEP_4;
331 }
332 state = &(((int32_t *)arg_state)[1]); /* first location */
333 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
334 srandom(seed);
335 if (rand_type == TYPE_0)
336 state[-1] = rand_type;
337 else
338 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
339 return(ostate);
340}
341
342/*
343 * setstate:
344 *
345 * Restore the state from the given state array.
346 *
347 * Note: it is important that we also remember the locations of the pointers
348 * in the current state information, and restore the locations of the pointers
349 * from the old state information. This is done by multiplexing the pointer
350 * location into the zeroeth word of the state information.
351 *
352 * Note that due to the order in which things are done, it is OK to call
353 * setstate() with the same state as the current state.
354 *
355 * Returns a pointer to the old state information.
356 */
357char *
358setstate(const char *arg_state)
359{
360 int32_t *new_state = (int32_t *)arg_state;
361 int32_t type = new_state[0] % MAX_TYPES;
362 int32_t rear = new_state[0] / MAX_TYPES;
363 char *ostate = (char *)(&state[-1]);
364
365 if (rand_type == TYPE_0)
366 state[-1] = rand_type;
367 else
368 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
369 switch(type) {
370 case TYPE_0:
371 case TYPE_1:
372 case TYPE_2:
373 case TYPE_3:
374 case TYPE_4:
375 rand_type = type;
376 rand_deg = degrees[type];
377 rand_sep = seps[type];
378 break;
379 default:
380 return(NULL);
381 }
382 state = &new_state[1];
383 if (rand_type != TYPE_0) {
384 rptr = &state[rear];
385 fptr = &state[(rear + rand_sep) % rand_deg];
386 }
387 end_ptr = &state[rand_deg]; /* set end_ptr too */
388 return(ostate);
389}
390
391/*
392 * random:
393 *
394 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
395 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
396 * the same in all the other cases due to all the global variables that have
397 * been set up. The basic operation is to add the number at the rear pointer
398 * into the one at the front pointer. Then both pointers are advanced to
399 * the next location cyclically in the table. The value returned is the sum
400 * generated, reduced to 31 bits by throwing away the "least random" low bit.
401 *
402 * Note: the code takes advantage of the fact that both the front and
403 * rear pointers can't wrap on the same call by not testing the rear
404 * pointer if the front one has wrapped.
405 *
406 * Returns a 31-bit random number.
407 */
408long
409random(void)
410{
411 int32_t i;
412
413 if (rand_type == TYPE_0)
414 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
415 else {
416 *fptr += *rptr;
417 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
418 if (++fptr >= end_ptr) {
419 fptr = state;
420 ++rptr;
421 } else if (++rptr >= end_ptr)
422 rptr = state;
423 }
424 return((long)i);
425}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000000..e1e0b10605
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.3
@@ -0,0 +1,117 @@
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.13 2005/04/03 18:59:15 otto Exp $
32.\"
33.Dd February 16, 1994
34.Dt REALPATH 3
35.Os
36.Sh NAME
37.Nm realpath
38.Nd returns the canonicalized absolute pathname
39.Sh SYNOPSIS
40.Fd #include <sys/param.h>
41.Fd #include <stdlib.h>
42.Ft "char *"
43.Fn realpath "const char *pathname" "char resolved[PATH_MAX]"
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.
64.Pp
65The
66.Fn realpath
67function will resolve both absolute and relative paths
68and return the absolute pathname corresponding to
69.Fa pathname .
70All but the last component of
71.Fa pathname
72must exist when
73.Fn realpath
74is called.
75.Sh RETURN VALUES
76The
77.Fn realpath
78function returns
79.Fa resolved
80on success.
81If an error occurs,
82.Fn realpath
83returns
84.Dv NULL
85and the contents of
86.Fa resolved
87are undefined.
88.Sh ERRORS
89The function
90.Fn realpath
91may fail and set the external variable
92.Va errno
93for any of the errors specified for the library functions
94.Xr lstat 2 ,
95.Xr readlink 2 ,
96and
97.Xr getcwd 3 .
98.Sh SEE ALSO
99.Xr readlink 1 ,
100.Xr getcwd 3
101.Sh HISTORY
102The
103.Fn realpath
104function call first appeared in
105.Bx 4.4 .
106.Sh CAVEATS
107This implementation of
108.Fn realpath
109differs slightly from the Solaris implementation.
110The
111.Bx 4.4
112version always returns absolute pathnames,
113whereas the Solaris implementation will,
114under certain circumstances, return a relative
115.Fa resolved
116when given a relative
117.Fa pathname .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000000..62e06b00be
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.c
@@ -0,0 +1,198 @@
1/*
2 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The names of the authors may not be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
29#if 0
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/lib/libc/stdlib/realpath.c,v 1.9.2.1 2003/05/22 17:11:44 fjoe Exp $");
32#endif
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: realpath.c,v 1.12 2005/03/29 19:34:14 brad Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <sys/stat.h>
40
41#include <errno.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46/*
47 * char *realpath(const char *path, char resolved[PATH_MAX]);
48 *
49 * Find the real name of path, by removing all ".", ".." and symlink
50 * components. Returns (resolved) on success, or (NULL) on failure,
51 * in which case the path which caused trouble is left in (resolved).
52 */
53char *
54realpath(const char *path, char resolved[PATH_MAX])
55{
56 struct stat sb;
57 char *p, *q, *s;
58 size_t left_len, resolved_len;
59 unsigned symlinks;
60 int serrno, slen;
61 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
62
63 serrno = errno;
64 symlinks = 0;
65 if (path[0] == '/') {
66 resolved[0] = '/';
67 resolved[1] = '\0';
68 if (path[1] == '\0')
69 return (resolved);
70 resolved_len = 1;
71 left_len = strlcpy(left, path + 1, sizeof(left));
72 } else {
73 if (getcwd(resolved, PATH_MAX) == NULL) {
74 strlcpy(resolved, ".", PATH_MAX);
75 return (NULL);
76 }
77 resolved_len = strlen(resolved);
78 left_len = strlcpy(left, path, sizeof(left));
79 }
80 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
81 errno = ENAMETOOLONG;
82 return (NULL);
83 }
84
85 /*
86 * Iterate over path components in `left'.
87 */
88 while (left_len != 0) {
89 /*
90 * Extract the next path component and adjust `left'
91 * and its length.
92 */
93 p = strchr(left, '/');
94 s = p ? p : left + left_len;
95 if (s - left >= sizeof(next_token)) {
96 errno = ENAMETOOLONG;
97 return (NULL);
98 }
99 memcpy(next_token, left, s - left);
100 next_token[s - left] = '\0';
101 left_len -= s - left;
102 if (p != NULL)
103 memmove(left, s + 1, left_len + 1);
104 if (resolved[resolved_len - 1] != '/') {
105 if (resolved_len + 1 >= PATH_MAX) {
106 errno = ENAMETOOLONG;
107 return (NULL);
108 }
109 resolved[resolved_len++] = '/';
110 resolved[resolved_len] = '\0';
111 }
112 if (next_token[0] == '\0')
113 continue;
114 else if (strcmp(next_token, ".") == 0)
115 continue;
116 else if (strcmp(next_token, "..") == 0) {
117 /*
118 * Strip the last path component except when we have
119 * single "/"
120 */
121 if (resolved_len > 1) {
122 resolved[resolved_len - 1] = '\0';
123 q = strrchr(resolved, '/') + 1;
124 *q = '\0';
125 resolved_len = q - resolved;
126 }
127 continue;
128 }
129
130 /*
131 * Append the next path component and lstat() it. If
132 * lstat() fails we still can return successfully if
133 * there are no more path components left.
134 */
135 resolved_len = strlcat(resolved, next_token, PATH_MAX);
136 if (resolved_len >= PATH_MAX) {
137 errno = ENAMETOOLONG;
138 return (NULL);
139 }
140 if (lstat(resolved, &sb) != 0) {
141 if (errno == ENOENT && p == NULL) {
142 errno = serrno;
143 return (resolved);
144 }
145 return (NULL);
146 }
147 if (S_ISLNK(sb.st_mode)) {
148 if (symlinks++ > MAXSYMLINKS) {
149 errno = ELOOP;
150 return (NULL);
151 }
152 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
153 if (slen < 0)
154 return (NULL);
155 symlink[slen] = '\0';
156 if (symlink[0] == '/') {
157 resolved[1] = 0;
158 resolved_len = 1;
159 } else if (resolved_len > 1) {
160 /* Strip the last path component. */
161 resolved[resolved_len - 1] = '\0';
162 q = strrchr(resolved, '/') + 1;
163 *q = '\0';
164 resolved_len = q - resolved;
165 }
166
167 /*
168 * If there are any path components left, then
169 * append them to symlink. The result is placed
170 * in `left'.
171 */
172 if (p != NULL) {
173 if (symlink[slen - 1] != '/') {
174 if (slen + 1 >= sizeof(symlink)) {
175 errno = ENAMETOOLONG;
176 return (NULL);
177 }
178 symlink[slen] = '/';
179 symlink[slen + 1] = 0;
180 }
181 left_len = strlcat(symlink, left, sizeof(left));
182 if (left_len >= sizeof(left)) {
183 errno = ENAMETOOLONG;
184 return (NULL);
185 }
186 }
187 left_len = strlcpy(left, symlink, sizeof(left));
188 }
189 }
190
191 /*
192 * Remove trailing slash except when the resolved pathname
193 * is a single "/".
194 */
195 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
196 resolved[resolved_len - 1] = '\0';
197 return (resolved);
198}
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..f4c5769a8c
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43remque(void *element)
44{
45 struct qelem *e = (struct qelem *) element;
46 e->q_forw->q_back = e->q_back;
47 e->q_back->q_forw = e->q_forw;
48}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
new file mode 100644
index 0000000000..c4dcd0ead8
--- /dev/null
+++ b/src/lib/libc/stdlib/seed48.c
@@ -0,0 +1,40 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: seed48.c,v 1.2 1996/08/19 08:33:48 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24unsigned short *
25seed48(unsigned short xseed[3])
26{
27 static unsigned short sseed[3];
28
29 sseed[0] = __rand48_seed[0];
30 sseed[1] = __rand48_seed[1];
31 sseed[2] = __rand48_seed[2];
32 __rand48_seed[0] = xseed[0];
33 __rand48_seed[1] = xseed[1];
34 __rand48_seed[2] = xseed[2];
35 __rand48_mult[0] = RAND48_MULT_0;
36 __rand48_mult[1] = RAND48_MULT_1;
37 __rand48_mult[2] = RAND48_MULT_2;
38 __rand48_add = RAND48_ADD;
39 return sseed;
40}
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
new file mode 100644
index 0000000000..ce0d3f9699
--- /dev/null
+++ b/src/lib/libc/stdlib/setenv.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: setenv.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37char *__findenv(const char *name, int *offset);
38
39extern char **environ;
40
41/*
42 * setenv --
43 * Set the value of the environmental variable "name" to be
44 * "value". If rewrite is set, replace any current value.
45 */
46int
47setenv(const char *name, const char *value, int rewrite)
48{
49 static char **lastenv; /* last value of environ */
50 char *C;
51 int l_value, offset;
52
53 if (*value == '=') /* no `=' in value */
54 ++value;
55 l_value = strlen(value);
56 if ((C = __findenv(name, &offset))) { /* find if already exists */
57 if (!rewrite)
58 return (0);
59 if (strlen(C) >= l_value) { /* old larger; copy over */
60 while ((*C++ = *value++))
61 ;
62 return (0);
63 }
64 } else { /* create new slot */
65 size_t cnt;
66 char **P;
67
68 for (P = environ; *P != NULL; P++)
69 ;
70 cnt = P - environ;
71 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
72 if (!P)
73 return (-1);
74 if (lastenv != environ)
75 memcpy(P, environ, cnt * sizeof(char *));
76 lastenv = environ = P;
77 offset = cnt;
78 environ[cnt + 1] = NULL;
79 }
80 for (C = (char *)name; *C && *C != '='; ++C)
81 ; /* no `=' in name */
82 if (!(environ[offset] = /* name + `=' + value */
83 malloc((size_t)((int)(C - name) + l_value + 2))))
84 return (-1);
85 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
86 ;
87 for (*C++ = '='; (*C++ = *value++); )
88 ;
89 return (0);
90}
91
92/*
93 * unsetenv(name) --
94 * Delete environmental variable "name".
95 */
96void
97unsetenv(const char *name)
98{
99 char **P;
100 int offset;
101
102 while (__findenv(name, &offset)) /* if set multiple times */
103 for (P = &environ[offset];; ++P)
104 if (!(*P = *(P + 1)))
105 break;
106}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
new file mode 100644
index 0000000000..fcff8a172e
--- /dev/null
+++ b/src/lib/libc/stdlib/srand48.c
@@ -0,0 +1,34 @@
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
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: srand48.c,v 1.2 1996/08/19 08:33:49 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24void
25srand48(long seed)
26{
27 __rand48_seed[0] = RAND48_SEED_0;
28 __rand48_seed[1] = (unsigned short) seed;
29 __rand48_seed[2] = (unsigned short) (seed >> 16);
30 __rand48_mult[0] = RAND48_MULT_0;
31 __rand48_mult[1] = RAND48_MULT_1;
32 __rand48_mult[2] = RAND48_MULT_2;
33 __rand48_add = RAND48_ADD;
34}
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
new file mode 100644
index 0000000000..e25b0a5511
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.3
@@ -0,0 +1,113 @@
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.8 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRTOD 3
36.Os
37.Sh NAME
38.Nm strtod
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft double
45.Fn strtod "const char *nptr" "char **endptr"
46.Sh DESCRIPTION
47The
48.Fn strtod
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55The expected form of the string is an optional plus
56.Pq Ql +
57or minus sign
58.Pq Ql -
59followed by a sequence of digits optionally containing
60a decimal-point character, optionally followed by an exponent.
61An exponent consists of an
62.Sq E
63or
64.Sq e ,
65followed by an optional plus or minus sign, followed by a sequence of digits.
66.Pp
67Leading whitespace characters in the string (as defined by the
68.Xr isspace 3
69function) are skipped.
70.Sh RETURN VALUES
71The
72.Fn strtod
73function returns the converted value, if any.
74.Pp
75If
76.Fa endptr
77is not
78.Dv NULL ,
79a pointer to the character after the last character used
80in the conversion is stored in the location referenced by
81.Fa endptr .
82.Pp
83If no conversion is performed, zero is returned and the value of
84.Fa nptr
85is stored in the location referenced by
86.Fa endptr .
87.Pp
88If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL
90is returned (according to the sign of the value), and
91.Er ERANGE
92is stored in
93.Va errno .
94If the correct value would cause underflow, zero is returned and
95.Er ERANGE
96is stored in
97.Va errno .
98.Sh ERRORS
99.Bl -tag -width Er
100.It Bq Er ERANGE
101Overflow or underflow occurred.
102.El
103.Sh SEE ALSO
104.Xr atof 3 ,
105.Xr atoi 3 ,
106.Xr atol 3 ,
107.Xr strtol 3 ,
108.Xr strtoul 3
109.Sh STANDARDS
110The
111.Fn strtod
112function conforms to
113.St -ansiC .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
new file mode 100644
index 0000000000..94eca88659
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2411 @@
1/****************************************************************
2 *
3 * The author of this software is David M. Gay.
4 *
5 * Copyright (c) 1991 by AT&T.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose without fee is hereby granted, provided that this entire notice
9 * is included in all copies of any software which is or includes a copy
10 * or modification of this software and in all copies of the supporting
11 * documentation for such software.
12 *
13 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
14 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
15 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
16 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
17 *
18 ***************************************************************/
19
20/* Please send bug reports to
21 David M. Gay
22 AT&T Bell Laboratories, Room 2C-463
23 600 Mountain Avenue
24 Murray Hill, NJ 07974-2070
25 U.S.A.
26 dmg@research.att.com or research!dmg
27 */
28
29/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
30 *
31 * This strtod returns a nearest machine number to the input decimal
32 * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
33 * broken by the IEEE round-even rule. Otherwise ties are broken by
34 * biased rounding (add half and chop).
35 *
36 * Inspired loosely by William D. Clinger's paper "How to Read Floating
37 * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
38 *
39 * Modifications:
40 *
41 * 1. We only require IEEE, IBM, or VAX double-precision
42 * arithmetic (not IEEE double-extended).
43 * 2. We get by with floating-point arithmetic in a case that
44 * Clinger missed -- when we're computing d * 10^n
45 * for a small integer d and the integer n is not too
46 * much larger than 22 (the maximum integer k for which
47 * we can represent 10^k exactly), we may be able to
48 * compute (d*10^k) * 10^(e-k) with just one roundoff.
49 * 3. Rather than a bit-at-a-time adjustment of the binary
50 * result in the hard case, we use floating-point
51 * arithmetic to determine the adjustment to within
52 * one bit; only in really hard cases do we need to
53 * compute a second residual.
54 * 4. Because of 3., we don't need a large table of powers of 10
55 * for ten-to-e (just some small tables, e.g. of 10^k
56 * for 0 <= k <= 22).
57 */
58
59/*
60 * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
61 * significant byte has the lowest address.
62 * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
63 * significant byte has the lowest address.
64 * #define Long int on machines with 32-bit ints and 64-bit longs.
65 * #define Sudden_Underflow for IEEE-format machines without gradual
66 * underflow (i.e., that flush to zero on underflow).
67 * #define IBM for IBM mainframe-style floating-point arithmetic.
68 * #define VAX for VAX-style floating-point arithmetic.
69 * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
70 * #define No_leftright to omit left-right logic in fast floating-point
71 * computation of dtoa.
72 * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
73 * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
74 * that use extended-precision instructions to compute rounded
75 * products and quotients) with IBM.
76 * #define ROUND_BIASED for IEEE-format with biased rounding.
77 * #define Inaccurate_Divide for IEEE-format with correctly rounded
78 * products but inaccurate quotients, e.g., for Intel i860.
79 * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
80 * integer arithmetic. Whether this speeds things up or slows things
81 * down depends on the machine and the number being converted.
82 * #define Bad_float_h if your system lacks a float.h or if it does not
83 * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
84 * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
85 * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
86 * if memory is available and otherwise does something you deem
87 * appropriate. If MALLOC is undefined, malloc will be invoked
88 * directly -- and assumed always to succeed.
89 */
90
91#if defined(LIBC_SCCS) && !defined(lint)
92static char *rcsid = "$OpenBSD: strtod.c,v 1.20 2005/03/30 18:51:49 pat Exp $";
93#endif /* LIBC_SCCS and not lint */
94
95#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
96 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
97 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__) || \
98 defined(__x86_64__) || (defined(__arm__) && defined(__VFP_FP__))
99#include <sys/types.h>
100#if BYTE_ORDER == BIG_ENDIAN
101#define IEEE_BIG_ENDIAN
102#else
103#define IEEE_LITTLE_ENDIAN
104#endif
105#endif
106
107#if defined(__arm__) && !defined(__VFP_FP__)
108/*
109 * Although the CPU is little endian the FP has different
110 * byte and word endianness. The byte order is still little endian
111 * but the word order is big endian.
112 */
113#define IEEE_BIG_ENDIAN
114#endif
115
116#ifdef __vax__
117#define VAX
118#endif
119
120#define Long int32_t
121#define ULong u_int32_t
122
123#ifdef DEBUG
124#include "stdio.h"
125#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
126#endif
127
128#ifdef __cplusplus
129#include "malloc.h"
130#include "memory.h"
131#else
132#include "stdlib.h"
133#include "string.h"
134#include "locale.h"
135#endif
136
137#ifdef MALLOC
138extern void *MALLOC(size_t);
139#else
140#define MALLOC malloc
141#endif
142
143#include "ctype.h"
144#include "errno.h"
145
146#ifdef Bad_float_h
147#ifdef IEEE_BIG_ENDIAN
148#define IEEE_ARITHMETIC
149#endif
150#ifdef IEEE_LITTLE_ENDIAN
151#define IEEE_ARITHMETIC
152#endif
153
154#ifdef IEEE_ARITHMETIC
155#define DBL_DIG 15
156#define DBL_MAX_10_EXP 308
157#define DBL_MAX_EXP 1024
158#define FLT_RADIX 2
159#define FLT_ROUNDS 1
160#define DBL_MAX 1.7976931348623157e+308
161#endif
162
163#ifdef IBM
164#define DBL_DIG 16
165#define DBL_MAX_10_EXP 75
166#define DBL_MAX_EXP 63
167#define FLT_RADIX 16
168#define FLT_ROUNDS 0
169#define DBL_MAX 7.2370055773322621e+75
170#endif
171
172#ifdef VAX
173#define DBL_DIG 16
174#define DBL_MAX_10_EXP 38
175#define DBL_MAX_EXP 127
176#define FLT_RADIX 2
177#define FLT_ROUNDS 1
178#define DBL_MAX 1.7014118346046923e+38
179#endif
180
181#ifndef LONG_MAX
182#define LONG_MAX 2147483647
183#endif
184#else
185#include "float.h"
186#endif
187#ifndef __MATH_H__
188#include "math.h"
189#endif
190
191#ifdef __cplusplus
192extern "C" {
193#endif
194
195#ifndef CONST
196#define CONST const
197#endif
198
199#ifdef Unsigned_Shifts
200#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
201#else
202#define Sign_Extend(a,b) /*no-op*/
203#endif
204
205#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
206 defined(IBM) != 1
207Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
208IBM should be defined.
209#endif
210
211typedef union {
212 double d;
213 ULong ul[2];
214} _double;
215#define value(x) ((x).d)
216#ifdef IEEE_LITTLE_ENDIAN
217#define word0(x) ((x).ul[1])
218#define word1(x) ((x).ul[0])
219#else
220#define word0(x) ((x).ul[0])
221#define word1(x) ((x).ul[1])
222#endif
223
224/* The following definition of Storeinc is appropriate for MIPS processors.
225 * An alternative that might be better on some machines is
226 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
227 */
228#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
229#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
230((unsigned short *)a)[0] = (unsigned short)c, a++)
231#else
232#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
233((unsigned short *)a)[1] = (unsigned short)c, a++)
234#endif
235
236/* #define P DBL_MANT_DIG */
237/* Ten_pmax = floor(P*log(2)/log(5)) */
238/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
239/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
240/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
241
242#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
243#define Exp_shift 20
244#define Exp_shift1 20
245#define Exp_msk1 0x100000
246#define Exp_msk11 0x100000
247#define Exp_mask 0x7ff00000
248#define P 53
249#define Bias 1023
250#define IEEE_Arith
251#define Emin (-1022)
252#define Exp_1 0x3ff00000
253#define Exp_11 0x3ff00000
254#define Ebits 11
255#define Frac_mask 0xfffff
256#define Frac_mask1 0xfffff
257#define Ten_pmax 22
258#define Bletch 0x10
259#define Bndry_mask 0xfffff
260#define Bndry_mask1 0xfffff
261#define LSB 1
262#define Sign_bit 0x80000000
263#define Log2P 1
264#define Tiny0 0
265#define Tiny1 1
266#define Quick_max 14
267#define Int_max 14
268#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
269#else
270#undef Sudden_Underflow
271#define Sudden_Underflow
272#ifdef IBM
273#define Exp_shift 24
274#define Exp_shift1 24
275#define Exp_msk1 0x1000000
276#define Exp_msk11 0x1000000
277#define Exp_mask 0x7f000000
278#define P 14
279#define Bias 65
280#define Exp_1 0x41000000
281#define Exp_11 0x41000000
282#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
283#define Frac_mask 0xffffff
284#define Frac_mask1 0xffffff
285#define Bletch 4
286#define Ten_pmax 22
287#define Bndry_mask 0xefffff
288#define Bndry_mask1 0xffffff
289#define LSB 1
290#define Sign_bit 0x80000000
291#define Log2P 4
292#define Tiny0 0x100000
293#define Tiny1 0
294#define Quick_max 14
295#define Int_max 15
296#else /* VAX */
297#define Exp_shift 23
298#define Exp_shift1 7
299#define Exp_msk1 0x80
300#define Exp_msk11 0x800000
301#define Exp_mask 0x7f80
302#define P 56
303#define Bias 129
304#define Exp_1 0x40800000
305#define Exp_11 0x4080
306#define Ebits 8
307#define Frac_mask 0x7fffff
308#define Frac_mask1 0xffff007f
309#define Ten_pmax 24
310#define Bletch 2
311#define Bndry_mask 0xffff007f
312#define Bndry_mask1 0xffff007f
313#define LSB 0x10000
314#define Sign_bit 0x8000
315#define Log2P 1
316#define Tiny0 0x80
317#define Tiny1 0
318#define Quick_max 15
319#define Int_max 15
320#endif
321#endif
322
323#ifndef IEEE_Arith
324#define ROUND_BIASED
325#endif
326
327#ifdef RND_PRODQUOT
328#define rounded_product(a,b) a = rnd_prod(a, b)
329#define rounded_quotient(a,b) a = rnd_quot(a, b)
330extern double rnd_prod(double, double), rnd_quot(double, double);
331#else
332#define rounded_product(a,b) a *= b
333#define rounded_quotient(a,b) a /= b
334#endif
335
336#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
337#define Big1 0xffffffff
338
339#ifndef Just_16
340/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
341 * This makes some inner loops simpler and sometimes saves work
342 * during multiplications, but it often seems to make things slightly
343 * slower. Hence the default is now to store 32 bits per Long.
344 */
345#ifndef Pack_32
346#define Pack_32
347#endif
348#endif
349
350#define Kmax 15
351
352#ifdef __cplusplus
353extern "C" double strtod(const char *s00, char **se);
354extern "C" char *__dtoa(double d, int mode, int ndigits,
355 int *decpt, int *sign, char **rve);
356#endif
357
358 struct
359Bigint {
360 struct Bigint *next;
361 int k, maxwds, sign, wds;
362 ULong x[1];
363 };
364
365 typedef struct Bigint Bigint;
366
367 static Bigint *freelist[Kmax+1];
368
369 static Bigint *
370Balloc(int k)
371{
372 int x;
373 Bigint *rv;
374
375 if ((rv = freelist[k])) {
376 freelist[k] = rv->next;
377 }
378 else {
379 x = 1 << k;
380 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
381 rv->k = k;
382 rv->maxwds = x;
383 }
384 rv->sign = rv->wds = 0;
385 return rv;
386 }
387
388 static void
389Bfree(Bigint *v)
390{
391 if (v) {
392 v->next = freelist[v->k];
393 freelist[v->k] = v;
394 }
395 }
396
397#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
398y->wds*sizeof(Long) + 2*sizeof(int))
399
400 static Bigint *
401multadd(Bigint *b, int m, int a) /* multiply by m and add a */
402{
403 int i, wds;
404 ULong *x, y;
405#ifdef Pack_32
406 ULong xi, z;
407#endif
408 Bigint *b1;
409
410 wds = b->wds;
411 x = b->x;
412 i = 0;
413 do {
414#ifdef Pack_32
415 xi = *x;
416 y = (xi & 0xffff) * m + a;
417 z = (xi >> 16) * m + (y >> 16);
418 a = (int)(z >> 16);
419 *x++ = (z << 16) + (y & 0xffff);
420#else
421 y = *x * m + a;
422 a = (int)(y >> 16);
423 *x++ = y & 0xffff;
424#endif
425 }
426 while(++i < wds);
427 if (a) {
428 if (wds >= b->maxwds) {
429 b1 = Balloc(b->k+1);
430 Bcopy(b1, b);
431 Bfree(b);
432 b = b1;
433 }
434 b->x[wds++] = a;
435 b->wds = wds;
436 }
437 return b;
438 }
439
440 static Bigint *
441s2b(CONST char *s, int nd0, int nd, ULong y9)
442{
443 Bigint *b;
444 int i, k;
445 Long x, y;
446
447 x = (nd + 8) / 9;
448 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
449#ifdef Pack_32
450 b = Balloc(k);
451 b->x[0] = y9;
452 b->wds = 1;
453#else
454 b = Balloc(k+1);
455 b->x[0] = y9 & 0xffff;
456 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
457#endif
458
459 i = 9;
460 if (9 < nd0) {
461 s += 9;
462 do b = multadd(b, 10, *s++ - '0');
463 while(++i < nd0);
464 s++;
465 }
466 else
467 s += 10;
468 for(; i < nd; i++)
469 b = multadd(b, 10, *s++ - '0');
470 return b;
471 }
472
473 static int
474hi0bits(ULong x)
475{
476 int k = 0;
477
478 if (!(x & 0xffff0000)) {
479 k = 16;
480 x <<= 16;
481 }
482 if (!(x & 0xff000000)) {
483 k += 8;
484 x <<= 8;
485 }
486 if (!(x & 0xf0000000)) {
487 k += 4;
488 x <<= 4;
489 }
490 if (!(x & 0xc0000000)) {
491 k += 2;
492 x <<= 2;
493 }
494 if (!(x & 0x80000000)) {
495 k++;
496 if (!(x & 0x40000000))
497 return 32;
498 }
499 return k;
500 }
501
502 static int
503lo0bits(ULong *y)
504{
505 int k;
506 ULong x = *y;
507
508 if (x & 7) {
509 if (x & 1)
510 return 0;
511 if (x & 2) {
512 *y = x >> 1;
513 return 1;
514 }
515 *y = x >> 2;
516 return 2;
517 }
518 k = 0;
519 if (!(x & 0xffff)) {
520 k = 16;
521 x >>= 16;
522 }
523 if (!(x & 0xff)) {
524 k += 8;
525 x >>= 8;
526 }
527 if (!(x & 0xf)) {
528 k += 4;
529 x >>= 4;
530 }
531 if (!(x & 0x3)) {
532 k += 2;
533 x >>= 2;
534 }
535 if (!(x & 1)) {
536 k++;
537 x >>= 1;
538 if (!x & 1)
539 return 32;
540 }
541 *y = x;
542 return k;
543 }
544
545 static Bigint *
546i2b(int i)
547{
548 Bigint *b;
549
550 b = Balloc(1);
551 b->x[0] = i;
552 b->wds = 1;
553 return b;
554 }
555
556 static Bigint *
557mult(Bigint *a, Bigint *b)
558{
559 Bigint *c;
560 int k, wa, wb, wc;
561 ULong carry, y, z;
562 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
563#ifdef Pack_32
564 ULong z2;
565#endif
566
567 if (a->wds < b->wds) {
568 c = a;
569 a = b;
570 b = c;
571 }
572 k = a->k;
573 wa = a->wds;
574 wb = b->wds;
575 wc = wa + wb;
576 if (wc > a->maxwds)
577 k++;
578 c = Balloc(k);
579 for(x = c->x, xa = x + wc; x < xa; x++)
580 *x = 0;
581 xa = a->x;
582 xae = xa + wa;
583 xb = b->x;
584 xbe = xb + wb;
585 xc0 = c->x;
586#ifdef Pack_32
587 for(; xb < xbe; xb++, xc0++) {
588 if ((y = *xb & 0xffff)) {
589 x = xa;
590 xc = xc0;
591 carry = 0;
592 do {
593 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
594 carry = z >> 16;
595 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
596 carry = z2 >> 16;
597 Storeinc(xc, z2, z);
598 }
599 while(x < xae);
600 *xc = carry;
601 }
602 if ((y = *xb >> 16)) {
603 x = xa;
604 xc = xc0;
605 carry = 0;
606 z2 = *xc;
607 do {
608 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
609 carry = z >> 16;
610 Storeinc(xc, z, z2);
611 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
612 carry = z2 >> 16;
613 }
614 while(x < xae);
615 *xc = z2;
616 }
617 }
618#else
619 for(; xb < xbe; xc0++) {
620 if (y = *xb++) {
621 x = xa;
622 xc = xc0;
623 carry = 0;
624 do {
625 z = *x++ * y + *xc + carry;
626 carry = z >> 16;
627 *xc++ = z & 0xffff;
628 }
629 while(x < xae);
630 *xc = carry;
631 }
632 }
633#endif
634 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
635 c->wds = wc;
636 return c;
637 }
638
639 static Bigint *p5s;
640
641 static Bigint *
642pow5mult(Bigint *b, int k)
643{
644 Bigint *b1, *p5, *p51;
645 int i;
646 static int p05[3] = { 5, 25, 125 };
647
648 if ((i = k & 3))
649 b = multadd(b, p05[i-1], 0);
650
651 if (!(k >>= 2))
652 return b;
653 if (!(p5 = p5s)) {
654 /* first time */
655 p5 = p5s = i2b(625);
656 p5->next = 0;
657 }
658 for(;;) {
659 if (k & 1) {
660 b1 = mult(b, p5);
661 Bfree(b);
662 b = b1;
663 }
664 if (!(k >>= 1))
665 break;
666 if (!(p51 = p5->next)) {
667 p51 = p5->next = mult(p5,p5);
668 p51->next = 0;
669 }
670 p5 = p51;
671 }
672 return b;
673 }
674
675 static Bigint *
676lshift(Bigint *b, int k)
677{
678 int i, k1, n, n1;
679 Bigint *b1;
680 ULong *x, *x1, *xe, z;
681
682#ifdef Pack_32
683 n = k >> 5;
684#else
685 n = k >> 4;
686#endif
687 k1 = b->k;
688 n1 = n + b->wds + 1;
689 for(i = b->maxwds; n1 > i; i <<= 1)
690 k1++;
691 b1 = Balloc(k1);
692 x1 = b1->x;
693 for(i = 0; i < n; i++)
694 *x1++ = 0;
695 x = b->x;
696 xe = x + b->wds;
697#ifdef Pack_32
698 if (k &= 0x1f) {
699 k1 = 32 - k;
700 z = 0;
701 do {
702 *x1++ = *x << k | z;
703 z = *x++ >> k1;
704 }
705 while(x < xe);
706 if ((*x1 = z))
707 ++n1;
708 }
709#else
710 if (k &= 0xf) {
711 k1 = 16 - k;
712 z = 0;
713 do {
714 *x1++ = *x << k & 0xffff | z;
715 z = *x++ >> k1;
716 }
717 while(x < xe);
718 if (*x1 = z)
719 ++n1;
720 }
721#endif
722 else do
723 *x1++ = *x++;
724 while(x < xe);
725 b1->wds = n1 - 1;
726 Bfree(b);
727 return b1;
728 }
729
730 static int
731cmp(Bigint *a, Bigint *b)
732{
733 ULong *xa, *xa0, *xb, *xb0;
734 int i, j;
735
736 i = a->wds;
737 j = b->wds;
738#ifdef DEBUG
739 if (i > 1 && !a->x[i-1])
740 Bug("cmp called with a->x[a->wds-1] == 0");
741 if (j > 1 && !b->x[j-1])
742 Bug("cmp called with b->x[b->wds-1] == 0");
743#endif
744 if (i -= j)
745 return i;
746 xa0 = a->x;
747 xa = xa0 + j;
748 xb0 = b->x;
749 xb = xb0 + j;
750 for(;;) {
751 if (*--xa != *--xb)
752 return *xa < *xb ? -1 : 1;
753 if (xa <= xa0)
754 break;
755 }
756 return 0;
757 }
758
759 static Bigint *
760diff(Bigint *a, Bigint *b)
761{
762 Bigint *c;
763 int i, wa, wb;
764 Long borrow, y; /* We need signed shifts here. */
765 ULong *xa, *xae, *xb, *xbe, *xc;
766#ifdef Pack_32
767 Long z;
768#endif
769
770 i = cmp(a,b);
771 if (!i) {
772 c = Balloc(0);
773 c->wds = 1;
774 c->x[0] = 0;
775 return c;
776 }
777 if (i < 0) {
778 c = a;
779 a = b;
780 b = c;
781 i = 1;
782 }
783 else
784 i = 0;
785 c = Balloc(a->k);
786 c->sign = i;
787 wa = a->wds;
788 xa = a->x;
789 xae = xa + wa;
790 wb = b->wds;
791 xb = b->x;
792 xbe = xb + wb;
793 xc = c->x;
794 borrow = 0;
795#ifdef Pack_32
796 do {
797 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
798 borrow = y >> 16;
799 Sign_Extend(borrow, y);
800 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
801 borrow = z >> 16;
802 Sign_Extend(borrow, z);
803 Storeinc(xc, z, y);
804 }
805 while(xb < xbe);
806 while(xa < xae) {
807 y = (*xa & 0xffff) + borrow;
808 borrow = y >> 16;
809 Sign_Extend(borrow, y);
810 z = (*xa++ >> 16) + borrow;
811 borrow = z >> 16;
812 Sign_Extend(borrow, z);
813 Storeinc(xc, z, y);
814 }
815#else
816 do {
817 y = *xa++ - *xb++ + borrow;
818 borrow = y >> 16;
819 Sign_Extend(borrow, y);
820 *xc++ = y & 0xffff;
821 }
822 while(xb < xbe);
823 while(xa < xae) {
824 y = *xa++ + borrow;
825 borrow = y >> 16;
826 Sign_Extend(borrow, y);
827 *xc++ = y & 0xffff;
828 }
829#endif
830 while(!*--xc)
831 wa--;
832 c->wds = wa;
833 return c;
834 }
835
836 static double
837ulp(double _x)
838{
839 _double x;
840 Long L;
841 _double a;
842
843 value(x) = _x;
844 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
845#ifndef Sudden_Underflow
846 if (L > 0) {
847#endif
848#ifdef IBM
849 L |= Exp_msk1 >> 4;
850#endif
851 word0(a) = L;
852 word1(a) = 0;
853#ifndef Sudden_Underflow
854 }
855 else {
856 L = -L >> Exp_shift;
857 if (L < Exp_shift) {
858 word0(a) = 0x80000 >> L;
859 word1(a) = 0;
860 }
861 else {
862 word0(a) = 0;
863 L -= Exp_shift;
864 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
865 }
866 }
867#endif
868 return value(a);
869 }
870
871 static double
872b2d(Bigint *a, int *e)
873{
874 ULong *xa, *xa0, w, y, z;
875 int k;
876 _double d;
877#ifdef VAX
878 ULong d0, d1;
879#else
880#define d0 word0(d)
881#define d1 word1(d)
882#endif
883
884 xa0 = a->x;
885 xa = xa0 + a->wds;
886 y = *--xa;
887#ifdef DEBUG
888 if (!y) Bug("zero y in b2d");
889#endif
890 k = hi0bits(y);
891 *e = 32 - k;
892#ifdef Pack_32
893 if (k < Ebits) {
894 d0 = Exp_1 | y >> Ebits - k;
895 w = xa > xa0 ? *--xa : 0;
896 d1 = y << (32-Ebits) + k | w >> Ebits - k;
897 goto ret_d;
898 }
899 z = xa > xa0 ? *--xa : 0;
900 if (k -= Ebits) {
901 d0 = Exp_1 | y << k | z >> 32 - k;
902 y = xa > xa0 ? *--xa : 0;
903 d1 = z << k | y >> 32 - k;
904 }
905 else {
906 d0 = Exp_1 | y;
907 d1 = z;
908 }
909#else
910 if (k < Ebits + 16) {
911 z = xa > xa0 ? *--xa : 0;
912 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
913 w = xa > xa0 ? *--xa : 0;
914 y = xa > xa0 ? *--xa : 0;
915 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
916 goto ret_d;
917 }
918 z = xa > xa0 ? *--xa : 0;
919 w = xa > xa0 ? *--xa : 0;
920 k -= Ebits + 16;
921 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
922 y = xa > xa0 ? *--xa : 0;
923 d1 = w << k + 16 | y << k;
924#endif
925 ret_d:
926#ifdef VAX
927 word0(d) = d0 >> 16 | d0 << 16;
928 word1(d) = d1 >> 16 | d1 << 16;
929#else
930#undef d0
931#undef d1
932#endif
933 return value(d);
934 }
935
936 static Bigint *
937d2b(double _d, int *e, int *bits)
938{
939 Bigint *b;
940 int de, i, k;
941 ULong *x, y, z;
942 _double d;
943#ifdef VAX
944 ULong d0, d1;
945#endif
946
947 value(d) = _d;
948#ifdef VAX
949 d0 = word0(d) >> 16 | word0(d) << 16;
950 d1 = word1(d) >> 16 | word1(d) << 16;
951#else
952#define d0 word0(d)
953#define d1 word1(d)
954#endif
955
956#ifdef Pack_32
957 b = Balloc(1);
958#else
959 b = Balloc(2);
960#endif
961 x = b->x;
962
963 z = d0 & Frac_mask;
964 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
965#ifdef Sudden_Underflow
966 de = (int)(d0 >> Exp_shift);
967#ifndef IBM
968 z |= Exp_msk11;
969#endif
970#else
971 if (de = (int)(d0 >> Exp_shift))
972 z |= Exp_msk1;
973#endif
974#ifdef Pack_32
975 if (y = d1) {
976 if (k = lo0bits(&y)) {
977 x[0] = y | z << 32 - k;
978 z >>= k;
979 }
980 else
981 x[0] = y;
982 i = b->wds = (x[1] = z) ? 2 : 1;
983 }
984 else {
985#ifdef DEBUG
986 if (!z)
987 Bug("Zero passed to d2b");
988#endif
989 k = lo0bits(&z);
990 x[0] = z;
991 i = b->wds = 1;
992 k += 32;
993 }
994#else
995 if (y = d1) {
996 if (k = lo0bits(&y))
997 if (k >= 16) {
998 x[0] = y | z << 32 - k & 0xffff;
999 x[1] = z >> k - 16 & 0xffff;
1000 x[2] = z >> k;
1001 i = 2;
1002 }
1003 else {
1004 x[0] = y & 0xffff;
1005 x[1] = y >> 16 | z << 16 - k & 0xffff;
1006 x[2] = z >> k & 0xffff;
1007 x[3] = z >> k+16;
1008 i = 3;
1009 }
1010 else {
1011 x[0] = y & 0xffff;
1012 x[1] = y >> 16;
1013 x[2] = z & 0xffff;
1014 x[3] = z >> 16;
1015 i = 3;
1016 }
1017 }
1018 else {
1019#ifdef DEBUG
1020 if (!z)
1021 Bug("Zero passed to d2b");
1022#endif
1023 k = lo0bits(&z);
1024 if (k >= 16) {
1025 x[0] = z;
1026 i = 0;
1027 }
1028 else {
1029 x[0] = z & 0xffff;
1030 x[1] = z >> 16;
1031 i = 1;
1032 }
1033 k += 32;
1034 }
1035 while(!x[i])
1036 --i;
1037 b->wds = i + 1;
1038#endif
1039#ifndef Sudden_Underflow
1040 if (de) {
1041#endif
1042#ifdef IBM
1043 *e = (de - Bias - (P-1) << 2) + k;
1044 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1045#else
1046 *e = de - Bias - (P-1) + k;
1047 *bits = P - k;
1048#endif
1049#ifndef Sudden_Underflow
1050 }
1051 else {
1052 *e = de - Bias - (P-1) + 1 + k;
1053#ifdef Pack_32
1054 *bits = 32*i - hi0bits(x[i-1]);
1055#else
1056 *bits = (i+2)*16 - hi0bits(x[i]);
1057#endif
1058 }
1059#endif
1060 return b;
1061 }
1062#undef d0
1063#undef d1
1064
1065 static double
1066ratio(Bigint *a, Bigint *b)
1067{
1068 _double da, db;
1069 int k, ka, kb;
1070
1071 value(da) = b2d(a, &ka);
1072 value(db) = b2d(b, &kb);
1073#ifdef Pack_32
1074 k = ka - kb + 32*(a->wds - b->wds);
1075#else
1076 k = ka - kb + 16*(a->wds - b->wds);
1077#endif
1078#ifdef IBM
1079 if (k > 0) {
1080 word0(da) += (k >> 2)*Exp_msk1;
1081 if (k &= 3)
1082 da *= 1 << k;
1083 }
1084 else {
1085 k = -k;
1086 word0(db) += (k >> 2)*Exp_msk1;
1087 if (k &= 3)
1088 db *= 1 << k;
1089 }
1090#else
1091 if (k > 0)
1092 word0(da) += k*Exp_msk1;
1093 else {
1094 k = -k;
1095 word0(db) += k*Exp_msk1;
1096 }
1097#endif
1098 return value(da) / value(db);
1099 }
1100
1101static CONST double
1102tens[] = {
1103 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1104 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1105 1e20, 1e21, 1e22
1106#ifdef VAX
1107 , 1e23, 1e24
1108#endif
1109 };
1110
1111#ifdef IEEE_Arith
1112static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1113static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1114#define n_bigtens 5
1115#else
1116#ifdef IBM
1117static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1118static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1119#define n_bigtens 3
1120#else
1121static CONST double bigtens[] = { 1e16, 1e32 };
1122static CONST double tinytens[] = { 1e-16, 1e-32 };
1123#define n_bigtens 2
1124#endif
1125#endif
1126
1127 double
1128strtod(CONST char *s00, char **se)
1129{
1130 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1131 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1132 CONST char *s, *s0, *s1;
1133 double aadj, aadj1, adj;
1134 _double rv, rv0;
1135 Long L;
1136 ULong y, z;
1137 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1138
1139 CONST char decimal_point = localeconv()->decimal_point[0];
1140
1141 sign = nz0 = nz = 0;
1142 value(rv) = 0.;
1143
1144
1145 for(s = s00; isspace((unsigned char) *s); s++)
1146 ;
1147
1148 if (*s == '-') {
1149 sign = 1;
1150 s++;
1151 } else if (*s == '+') {
1152 s++;
1153 }
1154
1155 if (*s == '\0') {
1156 s = s00;
1157 goto ret;
1158 }
1159
1160 if (*s == '0') {
1161 nz0 = 1;
1162 while(*++s == '0') ;
1163 if (!*s)
1164 goto ret;
1165 }
1166 s0 = s;
1167 y = z = 0;
1168 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1169 if (nd < 9)
1170 y = 10*y + c - '0';
1171 else if (nd < 16)
1172 z = 10*z + c - '0';
1173 nd0 = nd;
1174 if (c == decimal_point) {
1175 c = *++s;
1176 if (!nd) {
1177 for(; c == '0'; c = *++s)
1178 nz++;
1179 if (c > '0' && c <= '9') {
1180 s0 = s;
1181 nf += nz;
1182 nz = 0;
1183 goto have_dig;
1184 }
1185 goto dig_done;
1186 }
1187 for(; c >= '0' && c <= '9'; c = *++s) {
1188 have_dig:
1189 nz++;
1190 if (c -= '0') {
1191 nf += nz;
1192 for(i = 1; i < nz; i++)
1193 if (nd++ < 9)
1194 y *= 10;
1195 else if (nd <= DBL_DIG + 1)
1196 z *= 10;
1197 if (nd++ < 9)
1198 y = 10*y + c;
1199 else if (nd <= DBL_DIG + 1)
1200 z = 10*z + c;
1201 nz = 0;
1202 }
1203 }
1204 }
1205 dig_done:
1206 e = 0;
1207 if (c == 'e' || c == 'E') {
1208 if (!nd && !nz && !nz0) {
1209 s = s00;
1210 goto ret;
1211 }
1212 s00 = s;
1213 esign = 0;
1214 switch(c = *++s) {
1215 case '-':
1216 esign = 1;
1217 case '+':
1218 c = *++s;
1219 }
1220 if (c >= '0' && c <= '9') {
1221 while(c == '0')
1222 c = *++s;
1223 if (c > '0' && c <= '9') {
1224 L = c - '0';
1225 s1 = s;
1226 while((c = *++s) >= '0' && c <= '9')
1227 L = 10*L + c - '0';
1228 if (s - s1 > 8 || L > 19999)
1229 /* Avoid confusion from exponents
1230 * so large that e might overflow.
1231 */
1232 e = 19999; /* safe for 16 bit ints */
1233 else
1234 e = (int)L;
1235 if (esign)
1236 e = -e;
1237 }
1238 else
1239 e = 0;
1240 }
1241 else
1242 s = s00;
1243 }
1244 if (!nd) {
1245 if (!nz && !nz0)
1246 s = s00;
1247 goto ret;
1248 }
1249 e1 = e -= nf;
1250
1251 /* Now we have nd0 digits, starting at s0, followed by a
1252 * decimal point, followed by nd-nd0 digits. The number we're
1253 * after is the integer represented by those digits times
1254 * 10**e */
1255
1256 if (!nd0)
1257 nd0 = nd;
1258 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1259 value(rv) = y;
1260 if (k > 9)
1261 value(rv) = tens[k - 9] * value(rv) + z;
1262 bd0 = 0;
1263 if (nd <= DBL_DIG
1264#ifndef RND_PRODQUOT
1265 && FLT_ROUNDS == 1
1266#endif
1267 ) {
1268 if (!e)
1269 goto ret;
1270 if (e > 0) {
1271 if (e <= Ten_pmax) {
1272#ifdef VAX
1273 goto vax_ovfl_check;
1274#else
1275 /* value(rv) = */ rounded_product(value(rv),
1276 tens[e]);
1277 goto ret;
1278#endif
1279 }
1280 i = DBL_DIG - nd;
1281 if (e <= Ten_pmax + i) {
1282 /* A fancier test would sometimes let us do
1283 * this for larger i values.
1284 */
1285 e -= i;
1286 value(rv) *= tens[i];
1287#ifdef VAX
1288 /* VAX exponent range is so narrow we must
1289 * worry about overflow here...
1290 */
1291 vax_ovfl_check:
1292 word0(rv) -= P*Exp_msk1;
1293 /* value(rv) = */ rounded_product(value(rv),
1294 tens[e]);
1295 if ((word0(rv) & Exp_mask)
1296 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1297 goto ovfl;
1298 word0(rv) += P*Exp_msk1;
1299#else
1300 /* value(rv) = */ rounded_product(value(rv),
1301 tens[e]);
1302#endif
1303 goto ret;
1304 }
1305 }
1306#ifndef Inaccurate_Divide
1307 else if (e >= -Ten_pmax) {
1308 /* value(rv) = */ rounded_quotient(value(rv),
1309 tens[-e]);
1310 goto ret;
1311 }
1312#endif
1313 }
1314 e1 += nd - k;
1315
1316 /* Get starting approximation = rv * 10**e1 */
1317
1318 if (e1 > 0) {
1319 if (i = e1 & 15)
1320 value(rv) *= tens[i];
1321 if (e1 &= ~15) {
1322 if (e1 > DBL_MAX_10_EXP) {
1323 ovfl:
1324 errno = ERANGE;
1325#ifndef Bad_float_h
1326 value(rv) = HUGE_VAL;
1327#else
1328 /* Can't trust HUGE_VAL */
1329#ifdef IEEE_Arith
1330 word0(rv) = Exp_mask;
1331 word1(rv) = 0;
1332#else
1333 word0(rv) = Big0;
1334 word1(rv) = Big1;
1335#endif
1336#endif
1337 if (bd0)
1338 goto retfree;
1339 goto ret;
1340 }
1341 if (e1 >>= 4) {
1342 for(j = 0; e1 > 1; j++, e1 >>= 1)
1343 if (e1 & 1)
1344 value(rv) *= bigtens[j];
1345 /* The last multiplication could overflow. */
1346 word0(rv) -= P*Exp_msk1;
1347 value(rv) *= bigtens[j];
1348 if ((z = word0(rv) & Exp_mask)
1349 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1350 goto ovfl;
1351 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1352 /* set to largest number */
1353 /* (Can't trust DBL_MAX) */
1354 word0(rv) = Big0;
1355 word1(rv) = Big1;
1356 }
1357 else
1358 word0(rv) += P*Exp_msk1;
1359 }
1360
1361 }
1362 }
1363 else if (e1 < 0) {
1364 e1 = -e1;
1365 if (i = e1 & 15)
1366 value(rv) /= tens[i];
1367 if (e1 &= ~15) {
1368 e1 >>= 4;
1369 if (e1 >= 1 << n_bigtens)
1370 goto undfl;
1371 for(j = 0; e1 > 1; j++, e1 >>= 1)
1372 if (e1 & 1)
1373 value(rv) *= tinytens[j];
1374 /* The last multiplication could underflow. */
1375 value(rv0) = value(rv);
1376 value(rv) *= tinytens[j];
1377 if (!value(rv)) {
1378 value(rv) = 2.*value(rv0);
1379 value(rv) *= tinytens[j];
1380 if (!value(rv)) {
1381 undfl:
1382 value(rv) = 0.;
1383 errno = ERANGE;
1384 if (bd0)
1385 goto retfree;
1386 goto ret;
1387 }
1388 word0(rv) = Tiny0;
1389 word1(rv) = Tiny1;
1390 /* The refinement below will clean
1391 * this approximation up.
1392 */
1393 }
1394 }
1395 }
1396
1397 /* Now the hard part -- adjusting rv to the correct value.*/
1398
1399 /* Put digits into bd: true value = bd * 10^e */
1400
1401 bd0 = s2b(s0, nd0, nd, y);
1402
1403 for(;;) {
1404 bd = Balloc(bd0->k);
1405 Bcopy(bd, bd0);
1406 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1407 bs = i2b(1);
1408
1409 if (e >= 0) {
1410 bb2 = bb5 = 0;
1411 bd2 = bd5 = e;
1412 }
1413 else {
1414 bb2 = bb5 = -e;
1415 bd2 = bd5 = 0;
1416 }
1417 if (bbe >= 0)
1418 bb2 += bbe;
1419 else
1420 bd2 -= bbe;
1421 bs2 = bb2;
1422#ifdef Sudden_Underflow
1423#ifdef IBM
1424 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1425#else
1426 j = P + 1 - bbbits;
1427#endif
1428#else
1429 i = bbe + bbbits - 1; /* logb(rv) */
1430 if (i < Emin) /* denormal */
1431 j = bbe + (P-Emin);
1432 else
1433 j = P + 1 - bbbits;
1434#endif
1435 bb2 += j;
1436 bd2 += j;
1437 i = bb2 < bd2 ? bb2 : bd2;
1438 if (i > bs2)
1439 i = bs2;
1440 if (i > 0) {
1441 bb2 -= i;
1442 bd2 -= i;
1443 bs2 -= i;
1444 }
1445 if (bb5 > 0) {
1446 bs = pow5mult(bs, bb5);
1447 bb1 = mult(bs, bb);
1448 Bfree(bb);
1449 bb = bb1;
1450 }
1451 if (bb2 > 0)
1452 bb = lshift(bb, bb2);
1453 if (bd5 > 0)
1454 bd = pow5mult(bd, bd5);
1455 if (bd2 > 0)
1456 bd = lshift(bd, bd2);
1457 if (bs2 > 0)
1458 bs = lshift(bs, bs2);
1459 delta = diff(bb, bd);
1460 dsign = delta->sign;
1461 delta->sign = 0;
1462 i = cmp(delta, bs);
1463 if (i < 0) {
1464 /* Error is less than half an ulp -- check for
1465 * special case of mantissa a power of two.
1466 */
1467 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1468 break;
1469 delta = lshift(delta,Log2P);
1470 if (cmp(delta, bs) > 0)
1471 goto drop_down;
1472 break;
1473 }
1474 if (i == 0) {
1475 /* exactly half-way between */
1476 if (dsign) {
1477 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1478 && word1(rv) == 0xffffffff) {
1479 /*boundary case -- increment exponent*/
1480 word0(rv) = (word0(rv) & Exp_mask)
1481 + Exp_msk1
1482#ifdef IBM
1483 | Exp_msk1 >> 4
1484#endif
1485 ;
1486 word1(rv) = 0;
1487 break;
1488 }
1489 }
1490 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1491 drop_down:
1492 /* boundary case -- decrement exponent */
1493#ifdef Sudden_Underflow
1494 L = word0(rv) & Exp_mask;
1495#ifdef IBM
1496 if (L < Exp_msk1)
1497#else
1498 if (L <= Exp_msk1)
1499#endif
1500 goto undfl;
1501 L -= Exp_msk1;
1502#else
1503 L = (word0(rv) & Exp_mask) - Exp_msk1;
1504#endif
1505 word0(rv) = L | Bndry_mask1;
1506 word1(rv) = 0xffffffff;
1507#ifdef IBM
1508 goto cont;
1509#else
1510 break;
1511#endif
1512 }
1513#ifndef ROUND_BIASED
1514 if (!(word1(rv) & LSB))
1515 break;
1516#endif
1517 if (dsign)
1518 value(rv) += ulp(value(rv));
1519#ifndef ROUND_BIASED
1520 else {
1521 value(rv) -= ulp(value(rv));
1522#ifndef Sudden_Underflow
1523 if (!value(rv))
1524 goto undfl;
1525#endif
1526 }
1527#endif
1528 break;
1529 }
1530 if ((aadj = ratio(delta, bs)) <= 2.) {
1531 if (dsign)
1532 aadj = aadj1 = 1.;
1533 else if (word1(rv) || word0(rv) & Bndry_mask) {
1534#ifndef Sudden_Underflow
1535 if (word1(rv) == Tiny1 && !word0(rv))
1536 goto undfl;
1537#endif
1538 aadj = 1.;
1539 aadj1 = -1.;
1540 }
1541 else {
1542 /* special case -- power of FLT_RADIX to be */
1543 /* rounded down... */
1544
1545 if (aadj < 2./FLT_RADIX)
1546 aadj = 1./FLT_RADIX;
1547 else
1548 aadj *= 0.5;
1549 aadj1 = -aadj;
1550 }
1551 }
1552 else {
1553 aadj *= 0.5;
1554 aadj1 = dsign ? aadj : -aadj;
1555#ifdef Check_FLT_ROUNDS
1556 switch(FLT_ROUNDS) {
1557 case 2: /* towards +infinity */
1558 aadj1 -= 0.5;
1559 break;
1560 case 0: /* towards 0 */
1561 case 3: /* towards -infinity */
1562 aadj1 += 0.5;
1563 }
1564#else
1565 if (FLT_ROUNDS == 0)
1566 aadj1 += 0.5;
1567#endif
1568 }
1569 y = word0(rv) & Exp_mask;
1570
1571 /* Check for overflow */
1572
1573 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1574 value(rv0) = value(rv);
1575 word0(rv) -= P*Exp_msk1;
1576 adj = aadj1 * ulp(value(rv));
1577 value(rv) += adj;
1578 if ((word0(rv) & Exp_mask) >=
1579 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1580 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1581 goto ovfl;
1582 word0(rv) = Big0;
1583 word1(rv) = Big1;
1584 goto cont;
1585 }
1586 else
1587 word0(rv) += P*Exp_msk1;
1588 }
1589 else {
1590#ifdef Sudden_Underflow
1591 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1592 value(rv0) = value(rv);
1593 word0(rv) += P*Exp_msk1;
1594 adj = aadj1 * ulp(value(rv));
1595 value(rv) += adj;
1596#ifdef IBM
1597 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1598#else
1599 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1600#endif
1601 {
1602 if (word0(rv0) == Tiny0
1603 && word1(rv0) == Tiny1)
1604 goto undfl;
1605 word0(rv) = Tiny0;
1606 word1(rv) = Tiny1;
1607 goto cont;
1608 }
1609 else
1610 word0(rv) -= P*Exp_msk1;
1611 }
1612 else {
1613 adj = aadj1 * ulp(value(rv));
1614 value(rv) += adj;
1615 }
1616#else
1617 /* Compute adj so that the IEEE rounding rules will
1618 * correctly round rv + adj in some half-way cases.
1619 * If rv * ulp(rv) is denormalized (i.e.,
1620 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1621 * trouble from bits lost to denormalization;
1622 * example: 1.2e-307 .
1623 */
1624 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1625 aadj1 = (double)(int)(aadj + 0.5);
1626 if (!dsign)
1627 aadj1 = -aadj1;
1628 }
1629 adj = aadj1 * ulp(value(rv));
1630 value(rv) += adj;
1631#endif
1632 }
1633 z = word0(rv) & Exp_mask;
1634 if (y == z) {
1635 /* Can we stop now? */
1636 L = aadj;
1637 aadj -= L;
1638 /* The tolerances below are conservative. */
1639 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1640 if (aadj < .4999999 || aadj > .5000001)
1641 break;
1642 }
1643 else if (aadj < .4999999/FLT_RADIX)
1644 break;
1645 }
1646 cont:
1647 Bfree(bb);
1648 Bfree(bd);
1649 Bfree(bs);
1650 Bfree(delta);
1651 }
1652 retfree:
1653 Bfree(bb);
1654 Bfree(bd);
1655 Bfree(bs);
1656 Bfree(bd0);
1657 Bfree(delta);
1658 ret:
1659 if (se)
1660 *se = (char *)s;
1661 return sign ? -value(rv) : value(rv);
1662 }
1663
1664 static int
1665quorem(Bigint *b, Bigint *S)
1666{
1667 int n;
1668 Long borrow, y;
1669 ULong carry, q, ys;
1670 ULong *bx, *bxe, *sx, *sxe;
1671#ifdef Pack_32
1672 Long z;
1673 ULong si, zs;
1674#endif
1675
1676 n = S->wds;
1677#ifdef DEBUG
1678 /*debug*/ if (b->wds > n)
1679 /*debug*/ Bug("oversize b in quorem");
1680#endif
1681 if (b->wds < n)
1682 return 0;
1683 sx = S->x;
1684 sxe = sx + --n;
1685 bx = b->x;
1686 bxe = bx + n;
1687 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1688#ifdef DEBUG
1689 /*debug*/ if (q > 9)
1690 /*debug*/ Bug("oversized quotient in quorem");
1691#endif
1692 if (q) {
1693 borrow = 0;
1694 carry = 0;
1695 do {
1696#ifdef Pack_32
1697 si = *sx++;
1698 ys = (si & 0xffff) * q + carry;
1699 zs = (si >> 16) * q + (ys >> 16);
1700 carry = zs >> 16;
1701 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1702 borrow = y >> 16;
1703 Sign_Extend(borrow, y);
1704 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1705 borrow = z >> 16;
1706 Sign_Extend(borrow, z);
1707 Storeinc(bx, z, y);
1708#else
1709 ys = *sx++ * q + carry;
1710 carry = ys >> 16;
1711 y = *bx - (ys & 0xffff) + borrow;
1712 borrow = y >> 16;
1713 Sign_Extend(borrow, y);
1714 *bx++ = y & 0xffff;
1715#endif
1716 }
1717 while(sx <= sxe);
1718 if (!*bxe) {
1719 bx = b->x;
1720 while(--bxe > bx && !*bxe)
1721 --n;
1722 b->wds = n;
1723 }
1724 }
1725 if (cmp(b, S) >= 0) {
1726 q++;
1727 borrow = 0;
1728 carry = 0;
1729 bx = b->x;
1730 sx = S->x;
1731 do {
1732#ifdef Pack_32
1733 si = *sx++;
1734 ys = (si & 0xffff) + carry;
1735 zs = (si >> 16) + (ys >> 16);
1736 carry = zs >> 16;
1737 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1738 borrow = y >> 16;
1739 Sign_Extend(borrow, y);
1740 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1741 borrow = z >> 16;
1742 Sign_Extend(borrow, z);
1743 Storeinc(bx, z, y);
1744#else
1745 ys = *sx++ + carry;
1746 carry = ys >> 16;
1747 y = *bx - (ys & 0xffff) + borrow;
1748 borrow = y >> 16;
1749 Sign_Extend(borrow, y);
1750 *bx++ = y & 0xffff;
1751#endif
1752 }
1753 while(sx <= sxe);
1754 bx = b->x;
1755 bxe = bx + n;
1756 if (!*bxe) {
1757 while(--bxe > bx && !*bxe)
1758 --n;
1759 b->wds = n;
1760 }
1761 }
1762 return q;
1763 }
1764
1765/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1766 *
1767 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1768 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1769 *
1770 * Modifications:
1771 * 1. Rather than iterating, we use a simple numeric overestimate
1772 * to determine k = floor(log10(d)). We scale relevant
1773 * quantities using O(log2(k)) rather than O(k) multiplications.
1774 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1775 * try to generate digits strictly left to right. Instead, we
1776 * compute with fewer bits and propagate the carry if necessary
1777 * when rounding the final digit up. This is often faster.
1778 * 3. Under the assumption that input will be rounded nearest,
1779 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1780 * That is, we allow equality in stopping tests when the
1781 * round-nearest rule will give the same floating-point value
1782 * as would satisfaction of the stopping test with strict
1783 * inequality.
1784 * 4. We remove common factors of powers of 2 from relevant
1785 * quantities.
1786 * 5. When converting floating-point integers less than 1e16,
1787 * we use floating-point arithmetic rather than resorting
1788 * to multiple-precision integers.
1789 * 6. When asked to produce fewer than 15 digits, we first try
1790 * to get by with floating-point arithmetic; we resort to
1791 * multiple-precision integer arithmetic only if we cannot
1792 * guarantee that the floating-point calculation has given
1793 * the correctly rounded result. For k requested digits and
1794 * "uniformly" distributed input, the probability is
1795 * something like 10^(k-15) that we must resort to the Long
1796 * calculation.
1797 */
1798
1799 char *
1800__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1801{
1802 /* Arguments ndigits, decpt, sign are similar to those
1803 of ecvt and fcvt; trailing zeros are suppressed from
1804 the returned string. If not null, *rve is set to point
1805 to the end of the return value. If d is +-Infinity or NaN,
1806 then *decpt is set to 9999.
1807
1808 mode:
1809 0 ==> shortest string that yields d when read in
1810 and rounded to nearest.
1811 1 ==> like 0, but with Steele & White stopping rule;
1812 e.g. with IEEE P754 arithmetic , mode 0 gives
1813 1e23 whereas mode 1 gives 9.999999999999999e22.
1814 2 ==> max(1,ndigits) significant digits. This gives a
1815 return value similar to that of ecvt, except
1816 that trailing zeros are suppressed.
1817 3 ==> through ndigits past the decimal point. This
1818 gives a return value similar to that from fcvt,
1819 except that trailing zeros are suppressed, and
1820 ndigits can be negative.
1821 4-9 should give the same return values as 2-3, i.e.,
1822 4 <= mode <= 9 ==> same return as mode
1823 2 + (mode & 1). These modes are mainly for
1824 debugging; often they run slower but sometimes
1825 faster than modes 2-3.
1826 4,5,8,9 ==> left-to-right digit generation.
1827 6-9 ==> don't try fast floating-point estimate
1828 (if applicable).
1829
1830 Values of mode other than 0-9 are treated as mode 0.
1831
1832 Sufficient space is allocated to the return value
1833 to hold the suppressed trailing zeros.
1834 */
1835
1836 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1837 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1838 spec_case, try_quick;
1839 Long L;
1840#ifndef Sudden_Underflow
1841 int denorm;
1842 ULong x;
1843#endif
1844 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1845 double ds;
1846 char *s, *s0;
1847 static Bigint *result;
1848 static int result_k;
1849 _double d, d2, eps;
1850
1851 value(d) = _d;
1852 if (result) {
1853 result->k = result_k;
1854 result->maxwds = 1 << result_k;
1855 Bfree(result);
1856 result = 0;
1857 }
1858
1859 if (word0(d) & Sign_bit) {
1860 /* set sign for everything, including 0's and NaNs */
1861 *sign = 1;
1862 word0(d) &= ~Sign_bit; /* clear sign bit */
1863 }
1864 else
1865 *sign = 0;
1866
1867#if defined(IEEE_Arith) + defined(VAX)
1868#ifdef IEEE_Arith
1869 if ((word0(d) & Exp_mask) == Exp_mask)
1870#else
1871 if (word0(d) == 0x8000)
1872#endif
1873 {
1874 /* Infinity or NaN */
1875 *decpt = 9999;
1876 s =
1877#ifdef IEEE_Arith
1878 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1879#endif
1880 "NaN";
1881 if (rve)
1882 *rve =
1883#ifdef IEEE_Arith
1884 s[3] ? s + 8 :
1885#endif
1886 s + 3;
1887 return s;
1888 }
1889#endif
1890#ifdef IBM
1891 value(d) += 0; /* normalize */
1892#endif
1893 if (!value(d)) {
1894 *decpt = 1;
1895 s = "0";
1896 if (rve)
1897 *rve = s + 1;
1898 return s;
1899 }
1900
1901 b = d2b(value(d), &be, &bbits);
1902#ifdef Sudden_Underflow
1903 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1904#else
1905 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1906#endif
1907 value(d2) = value(d);
1908 word0(d2) &= Frac_mask1;
1909 word0(d2) |= Exp_11;
1910#ifdef IBM
1911 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1912 value(d2) /= 1 << j;
1913#endif
1914
1915 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
1916 * log10(x) = log(x) / log(10)
1917 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1918 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1919 *
1920 * This suggests computing an approximation k to log10(d) by
1921 *
1922 * k = (i - Bias)*0.301029995663981
1923 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1924 *
1925 * We want k to be too large rather than too small.
1926 * The error in the first-order Taylor series approximation
1927 * is in our favor, so we just round up the constant enough
1928 * to compensate for any error in the multiplication of
1929 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1930 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1931 * adding 1e-13 to the constant term more than suffices.
1932 * Hence we adjust the constant term to 0.1760912590558.
1933 * (We could get a more accurate k by invoking log10,
1934 * but this is probably not worthwhile.)
1935 */
1936
1937 i -= Bias;
1938#ifdef IBM
1939 i <<= 2;
1940 i += j;
1941#endif
1942#ifndef Sudden_Underflow
1943 denorm = 0;
1944 }
1945 else {
1946 /* d is denormalized */
1947
1948 i = bbits + be + (Bias + (P-1) - 1);
1949 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
1950 : word1(d) << 32 - i;
1951 value(d2) = x;
1952 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
1953 i -= (Bias + (P-1) - 1) + 1;
1954 denorm = 1;
1955 }
1956#endif
1957 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
1958 i*0.301029995663981;
1959 k = (int)ds;
1960 if (ds < 0. && ds != k)
1961 k--; /* want k = floor(ds) */
1962 k_check = 1;
1963 if (k >= 0 && k <= Ten_pmax) {
1964 if (value(d) < tens[k])
1965 k--;
1966 k_check = 0;
1967 }
1968 j = bbits - i - 1;
1969 if (j >= 0) {
1970 b2 = 0;
1971 s2 = j;
1972 }
1973 else {
1974 b2 = -j;
1975 s2 = 0;
1976 }
1977 if (k >= 0) {
1978 b5 = 0;
1979 s5 = k;
1980 s2 += k;
1981 }
1982 else {
1983 b2 -= k;
1984 b5 = -k;
1985 s5 = 0;
1986 }
1987 if (mode < 0 || mode > 9)
1988 mode = 0;
1989 try_quick = 1;
1990 if (mode > 5) {
1991 mode -= 4;
1992 try_quick = 0;
1993 }
1994 leftright = 1;
1995 switch(mode) {
1996 case 0:
1997 case 1:
1998 ilim = ilim1 = -1;
1999 i = 18;
2000 ndigits = 0;
2001 break;
2002 case 2:
2003 leftright = 0;
2004 /* no break */
2005 case 4:
2006 if (ndigits <= 0)
2007 ndigits = 1;
2008 ilim = ilim1 = i = ndigits;
2009 break;
2010 case 3:
2011 leftright = 0;
2012 /* no break */
2013 case 5:
2014 i = ndigits + k + 1;
2015 ilim = i;
2016 ilim1 = i - 1;
2017 if (i <= 0)
2018 i = 1;
2019 }
2020 j = sizeof(ULong);
2021 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2022 j <<= 1) result_k++;
2023 result = Balloc(result_k);
2024 s = s0 = (char *)result;
2025
2026 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2027
2028 /* Try to get by with floating-point arithmetic. */
2029
2030 i = 0;
2031 value(d2) = value(d);
2032 k0 = k;
2033 ilim0 = ilim;
2034 ieps = 2; /* conservative */
2035 if (k > 0) {
2036 ds = tens[k&0xf];
2037 j = k >> 4;
2038 if (j & Bletch) {
2039 /* prevent overflows */
2040 j &= Bletch - 1;
2041 value(d) /= bigtens[n_bigtens-1];
2042 ieps++;
2043 }
2044 for(; j; j >>= 1, i++)
2045 if (j & 1) {
2046 ieps++;
2047 ds *= bigtens[i];
2048 }
2049 value(d) /= ds;
2050 }
2051 else if (j1 = -k) {
2052 value(d) *= tens[j1 & 0xf];
2053 for(j = j1 >> 4; j; j >>= 1, i++)
2054 if (j & 1) {
2055 ieps++;
2056 value(d) *= bigtens[i];
2057 }
2058 }
2059 if (k_check && value(d) < 1. && ilim > 0) {
2060 if (ilim1 <= 0)
2061 goto fast_failed;
2062 ilim = ilim1;
2063 k--;
2064 value(d) *= 10.;
2065 ieps++;
2066 }
2067 value(eps) = ieps*value(d) + 7.;
2068 word0(eps) -= (P-1)*Exp_msk1;
2069 if (ilim == 0) {
2070 S = mhi = 0;
2071 value(d) -= 5.;
2072 if (value(d) > value(eps))
2073 goto one_digit;
2074 if (value(d) < -value(eps))
2075 goto no_digits;
2076 goto fast_failed;
2077 }
2078#ifndef No_leftright
2079 if (leftright) {
2080 /* Use Steele & White method of only
2081 * generating digits needed.
2082 */
2083 value(eps) = 0.5/tens[ilim-1] - value(eps);
2084 for(i = 0;;) {
2085 L = value(d);
2086 value(d) -= L;
2087 *s++ = '0' + (int)L;
2088 if (value(d) < value(eps))
2089 goto ret1;
2090 if (1. - value(d) < value(eps))
2091 goto bump_up;
2092 if (++i >= ilim)
2093 break;
2094 value(eps) *= 10.;
2095 value(d) *= 10.;
2096 }
2097 }
2098 else {
2099#endif
2100 /* Generate ilim digits, then fix them up. */
2101 value(eps) *= tens[ilim-1];
2102 for(i = 1;; i++, value(d) *= 10.) {
2103 L = value(d);
2104 value(d) -= L;
2105 *s++ = '0' + (int)L;
2106 if (i == ilim) {
2107 if (value(d) > 0.5 + value(eps))
2108 goto bump_up;
2109 else if (value(d) < 0.5 - value(eps)) {
2110 while(*--s == '0');
2111 s++;
2112 goto ret1;
2113 }
2114 break;
2115 }
2116 }
2117#ifndef No_leftright
2118 }
2119#endif
2120 fast_failed:
2121 s = s0;
2122 value(d) = value(d2);
2123 k = k0;
2124 ilim = ilim0;
2125 }
2126
2127 /* Do we have a "small" integer? */
2128
2129 if (be >= 0 && k <= Int_max) {
2130 /* Yes. */
2131 ds = tens[k];
2132 if (ndigits < 0 && ilim <= 0) {
2133 S = mhi = 0;
2134 if (ilim < 0 || value(d) <= 5*ds)
2135 goto no_digits;
2136 goto one_digit;
2137 }
2138 for(i = 1;; i++) {
2139 L = value(d) / ds;
2140 value(d) -= L*ds;
2141#ifdef Check_FLT_ROUNDS
2142 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2143 if (value(d) < 0) {
2144 L--;
2145 value(d) += ds;
2146 }
2147#endif
2148 *s++ = '0' + (int)L;
2149 if (i == ilim) {
2150 value(d) += value(d);
2151 if (value(d) > ds || value(d) == ds && L & 1) {
2152 bump_up:
2153 while(*--s == '9')
2154 if (s == s0) {
2155 k++;
2156 *s = '0';
2157 break;
2158 }
2159 ++*s++;
2160 }
2161 break;
2162 }
2163 if (!(value(d) *= 10.))
2164 break;
2165 }
2166 goto ret1;
2167 }
2168
2169 m2 = b2;
2170 m5 = b5;
2171 mhi = mlo = 0;
2172 if (leftright) {
2173 if (mode < 2) {
2174 i =
2175#ifndef Sudden_Underflow
2176 denorm ? be + (Bias + (P-1) - 1 + 1) :
2177#endif
2178#ifdef IBM
2179 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2180#else
2181 1 + P - bbits;
2182#endif
2183 }
2184 else {
2185 j = ilim - 1;
2186 if (m5 >= j)
2187 m5 -= j;
2188 else {
2189 s5 += j -= m5;
2190 b5 += j;
2191 m5 = 0;
2192 }
2193 if ((i = ilim) < 0) {
2194 m2 -= i;
2195 i = 0;
2196 }
2197 }
2198 b2 += i;
2199 s2 += i;
2200 mhi = i2b(1);
2201 }
2202 if (m2 > 0 && s2 > 0) {
2203 i = m2 < s2 ? m2 : s2;
2204 b2 -= i;
2205 m2 -= i;
2206 s2 -= i;
2207 }
2208 if (b5 > 0) {
2209 if (leftright) {
2210 if (m5 > 0) {
2211 mhi = pow5mult(mhi, m5);
2212 b1 = mult(mhi, b);
2213 Bfree(b);
2214 b = b1;
2215 }
2216 if (j = b5 - m5)
2217 b = pow5mult(b, j);
2218 }
2219 else
2220 b = pow5mult(b, b5);
2221 }
2222 S = i2b(1);
2223 if (s5 > 0)
2224 S = pow5mult(S, s5);
2225
2226 /* Check for special case that d is a normalized power of 2. */
2227
2228 if (mode < 2) {
2229 if (!word1(d) && !(word0(d) & Bndry_mask)
2230#ifndef Sudden_Underflow
2231 && word0(d) & Exp_mask
2232#endif
2233 ) {
2234 /* The special case */
2235 b2 += Log2P;
2236 s2 += Log2P;
2237 spec_case = 1;
2238 }
2239 else
2240 spec_case = 0;
2241 }
2242
2243 /* Arrange for convenient computation of quotients:
2244 * shift left if necessary so divisor has 4 leading 0 bits.
2245 *
2246 * Perhaps we should just compute leading 28 bits of S once
2247 * and for all and pass them and a shift to quorem, so it
2248 * can do shifts and ors to compute the numerator for q.
2249 */
2250#ifdef Pack_32
2251 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2252 i = 32 - i;
2253#else
2254 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2255 i = 16 - i;
2256#endif
2257 if (i > 4) {
2258 i -= 4;
2259 b2 += i;
2260 m2 += i;
2261 s2 += i;
2262 }
2263 else if (i < 4) {
2264 i += 28;
2265 b2 += i;
2266 m2 += i;
2267 s2 += i;
2268 }
2269 if (b2 > 0)
2270 b = lshift(b, b2);
2271 if (s2 > 0)
2272 S = lshift(S, s2);
2273 if (k_check) {
2274 if (cmp(b,S) < 0) {
2275 k--;
2276 b = multadd(b, 10, 0); /* we botched the k estimate */
2277 if (leftright)
2278 mhi = multadd(mhi, 10, 0);
2279 ilim = ilim1;
2280 }
2281 }
2282 if (ilim <= 0 && mode > 2) {
2283 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2284 /* no digits, fcvt style */
2285 no_digits:
2286 k = -1 - ndigits;
2287 goto ret;
2288 }
2289 one_digit:
2290 *s++ = '1';
2291 k++;
2292 goto ret;
2293 }
2294 if (leftright) {
2295 if (m2 > 0)
2296 mhi = lshift(mhi, m2);
2297
2298 /* Compute mlo -- check for special case
2299 * that d is a normalized power of 2.
2300 */
2301
2302 mlo = mhi;
2303 if (spec_case) {
2304 mhi = Balloc(mhi->k);
2305 Bcopy(mhi, mlo);
2306 mhi = lshift(mhi, Log2P);
2307 }
2308
2309 for(i = 1;;i++) {
2310 dig = quorem(b,S) + '0';
2311 /* Do we yet have the shortest decimal string
2312 * that will round to d?
2313 */
2314 j = cmp(b, mlo);
2315 delta = diff(S, mhi);
2316 j1 = delta->sign ? 1 : cmp(b, delta);
2317 Bfree(delta);
2318#ifndef ROUND_BIASED
2319 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2320 if (dig == '9')
2321 goto round_9_up;
2322 if (j > 0)
2323 dig++;
2324 *s++ = dig;
2325 goto ret;
2326 }
2327#endif
2328 if (j < 0 || j == 0 && !mode
2329#ifndef ROUND_BIASED
2330 && !(word1(d) & 1)
2331#endif
2332 ) {
2333 if (j1 > 0) {
2334 b = lshift(b, 1);
2335 j1 = cmp(b, S);
2336 if ((j1 > 0 || j1 == 0 && dig & 1)
2337 && dig++ == '9')
2338 goto round_9_up;
2339 }
2340 *s++ = dig;
2341 goto ret;
2342 }
2343 if (j1 > 0) {
2344 if (dig == '9') { /* possible if i == 1 */
2345 round_9_up:
2346 *s++ = '9';
2347 goto roundoff;
2348 }
2349 *s++ = dig + 1;
2350 goto ret;
2351 }
2352 *s++ = dig;
2353 if (i == ilim)
2354 break;
2355 b = multadd(b, 10, 0);
2356 if (mlo == mhi)
2357 mlo = mhi = multadd(mhi, 10, 0);
2358 else {
2359 mlo = multadd(mlo, 10, 0);
2360 mhi = multadd(mhi, 10, 0);
2361 }
2362 }
2363 }
2364 else
2365 for(i = 1;; i++) {
2366 *s++ = dig = quorem(b,S) + '0';
2367 if (i >= ilim)
2368 break;
2369 b = multadd(b, 10, 0);
2370 }
2371
2372 /* Round off last digit */
2373
2374 b = lshift(b, 1);
2375 j = cmp(b, S);
2376 if (j > 0 || j == 0 && dig & 1) {
2377 roundoff:
2378 while(*--s == '9')
2379 if (s == s0) {
2380 k++;
2381 *s++ = '1';
2382 goto ret;
2383 }
2384 ++*s++;
2385 }
2386 else {
2387 while(*--s == '0');
2388 s++;
2389 }
2390 ret:
2391 Bfree(S);
2392 if (mhi) {
2393 if (mlo && mlo != mhi)
2394 Bfree(mlo);
2395 Bfree(mhi);
2396 }
2397 ret1:
2398 Bfree(b);
2399 if (s == s0) { /* don't return empty string */
2400 *s++ = '0';
2401 k = 0;
2402 }
2403 *s = 0;
2404 *decpt = k + 1;
2405 if (rve)
2406 *rve = s;
2407 return s0;
2408 }
2409#ifdef __cplusplus
2410}
2411#endif
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
new file mode 100644
index 0000000000..3f5375c5e3
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.3
@@ -0,0 +1,247 @@
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.13 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 25, 1992
35.Dt STRTOL 3
36.Os
37.Sh NAME
38.Nm strtol ,
39.Nm strtoll ,
40.Nm strtoq
41.Nd "convert string value to a long or long long integer"
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Fd #include <limits.h>
45.Ft long
46.Fn strtol "const char *nptr" "char **endptr" "int base"
47.Pp
48.Fd #include <stdlib.h>
49.Fd #include <limits.h>
50.Ft long long
51.Fn strtoll "const char *nptr" "char **endptr" "int base"
52.Pp
53.Fd #include <sys/types.h>
54.Fd #include <stdlib.h>
55.Fd #include <limits.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.Li long
65value.
66The
67.Fn strtoll
68function converts the string in
69.Fa nptr
70to a
71.Li long long
72value.
73The
74.Fn strtoq
75function is a deprecated equivalent of
76.Fn strtoll
77and is provided for backwards compatibility with legacy programs.
78The conversion is done according to the given
79.Fa base ,
80which must be a number between 2 and 36 inclusive or the special value 0.
81.Pp
82The string may begin with an arbitrary amount of whitespace
83(as determined by
84.Xr isspace 3 )
85followed by a single optional
86.Ql +
87or
88.Ql -
89sign.
90If
91.Fa base
92is zero or 16, the string may then include a
93.Ql 0x
94prefix, and the number will be read in base 16; otherwise, a zero
95.Fa base
96is taken as 10 (decimal) unless the next character is
97.Ql 0 ,
98in which case it is taken as 8 (octal).
99.Pp
100The remainder of the string is converted to a
101.Li long
102value in the obvious manner,
103stopping at the first character which is not a valid digit
104in the given base.
105(In bases above 10, the letter
106.Ql A
107in either upper or lower case represents 10,
108.Ql B
109represents 11, and so forth, with
110.Ql Z
111representing 35.)
112.Pp
113If
114.Fa endptr
115is non-null,
116.Fn strtol
117stores the address of the first invalid character in
118.Fa *endptr .
119If there were no digits at all, however,
120.Fn strtol
121stores the original value of
122.Fa nptr
123in
124.Fa *endptr .
125(Thus, if
126.Fa *nptr
127is not
128.Ql \e0
129but
130.Fa **endptr
131is
132.Ql \e0
133on return, the entire string was valid.)
134.Sh RETURN VALUES
135The
136.Fn strtol
137function returns the result of the conversion,
138unless the value would underflow or overflow.
139If an underflow occurs,
140.Fn strtol
141returns
142.Dv LONG_MIN .
143If an overflow occurs,
144.Fn strtol
145returns
146.Dv LONG_MAX .
147In both cases,
148.Va errno
149is set to
150.Er ERANGE .
151.Pp
152The
153.Fn strtoll
154function has identical return values except that
155.Dv LLONG_MIN
156and
157.Dv LLONG_MAX
158are used to indicate underflow and overflow respectively.
159.Sh EXAMPLES
160Ensuring that a string is a valid number (i.e., in range and containing no
161trailing characters) requires clearing
162.Va errno
163beforehand explicitly since
164.Va errno
165is not changed on a successful call to
166.Fn strtol ,
167and the return value of
168.Fn strtol
169cannot be used unambiguously to signal an error:
170.Bd -literal -offset indent
171char *ep;
172long lval;
173
174\&...
175
176errno = 0;
177lval = strtol(buf, &ep, 10);
178if (buf[0] == '\e0' || *ep != '\e0')
179 goto not_a_number;
180if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
181 goto out_of_range;
182.Ed
183.Pp
184This example will accept
185.Dq 12
186but not
187.Dq 12foo
188or
189.Dq 12\en .
190If trailing whitespace is acceptable, further checks must be done on
191.Va *ep ;
192alternately, use
193.Xr sscanf 3 .
194.Pp
195If
196.Fn strtol
197is being used instead of
198.Xr atoi 3 ,
199error checking is further complicated because the desired return value is an
200.Li int
201rather than a
202.Li long ;
203however, on some architectures integers and long integers are the same size.
204Thus the following is necessary:
205.Bd -literal -offset indent
206char *ep;
207int ival;
208long lval;
209
210\&...
211
212errno = 0;
213lval = strtol(buf, &ep, 10);
214if (buf[0] == '\e0' || *ep != '\e0')
215 goto not_a_number;
216if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
217 (lval > INT_MAX || lval < INT_MIN))
218 goto out_of_range;
219ival = lval;
220.Ed
221.Sh ERRORS
222.Bl -tag -width Er
223.It Bq Er ERANGE
224The given string was out of range; the value converted has been clamped.
225.El
226.Sh SEE ALSO
227.Xr atof 3 ,
228.Xr atoi 3 ,
229.Xr atol 3 ,
230.Xr atoll 3 ,
231.Xr sscanf 3 ,
232.Xr strtod 3 ,
233.Xr strtoul 3
234.Sh STANDARDS
235The
236.Fn strtol
237and
238.Fn strtoll
239functions conform to
240.St -ansiC-99 .
241The
242.Fn strtoq
243function is a
244.Bx
245extension and is provided for backwards compatibility with legacy programs.
246.Sh BUGS
247Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
new file mode 100644
index 0000000000..9692bb6b07
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.c
@@ -0,0 +1,143 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strtol.c,v 1.6 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <ctype.h>
35#include <errno.h>
36#include <limits.h>
37#include <stdlib.h>
38
39
40/*
41 * Convert a string to a long integer.
42 *
43 * Ignores `locale' stuff. Assumes that the upper and lower case
44 * alphabets and digits are each contiguous.
45 */
46long
47strtol(const char *nptr, char **endptr, int base)
48{
49 const char *s;
50 long acc, cutoff;
51 int c;
52 int neg, any, cutlim;
53
54 /*
55 * Skip white space and pick up leading +/- sign if any.
56 * If base is 0, allow 0x for hex and 0 for octal, else
57 * assume decimal; if base is already 16, allow 0x.
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) &&
72 c == '0' && (*s == 'x' || *s == 'X')) {
73 c = s[1];
74 s += 2;
75 base = 16;
76 }
77 if (base == 0)
78 base = c == '0' ? 8 : 10;
79
80 /*
81 * Compute the cutoff value between legal numbers and illegal
82 * numbers. That is the largest legal value, divided by the
83 * base. An input number that is greater than this value, if
84 * followed by a legal input character, is too big. One that
85 * is equal to this value may be valid or not; the limit
86 * between valid and invalid numbers is then based on the last
87 * digit. For instance, if the range for longs is
88 * [-2147483648..2147483647] and the input base is 10,
89 * cutoff will be set to 214748364 and cutlim to either
90 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
91 * a value > 214748364, or equal but the next digit is > 7 (or 8),
92 * the number is too big, and we will return a range error.
93 *
94 * Set any if any `digits' consumed; make it negative to indicate
95 * overflow.
96 */
97 cutoff = neg ? LONG_MIN : LONG_MAX;
98 cutlim = cutoff % base;
99 cutoff /= base;
100 if (neg) {
101 if (cutlim > 0) {
102 cutlim -= base;
103 cutoff += 1;
104 }
105 cutlim = -cutlim;
106 }
107 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
108 if (isdigit(c))
109 c -= '0';
110 else if (isalpha(c))
111 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
112 else
113 break;
114 if (c >= base)
115 break;
116 if (any < 0)
117 continue;
118 if (neg) {
119 if (acc < cutoff || acc == cutoff && c > cutlim) {
120 any = -1;
121 acc = LONG_MIN;
122 errno = ERANGE;
123 } else {
124 any = 1;
125 acc *= base;
126 acc -= c;
127 }
128 } else {
129 if (acc > cutoff || acc == cutoff && c > cutlim) {
130 any = -1;
131 acc = LONG_MAX;
132 errno = ERANGE;
133 } else {
134 any = 1;
135 acc *= base;
136 acc += c;
137 }
138 }
139 }
140 if (endptr != 0)
141 *endptr = (char *) (any ? s - 1 : nptr);
142 return (acc);
143}
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000000..fa4d30ef5a
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,156 @@
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static const char rcsid[] = "$OpenBSD: strtoll.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35
36#include <ctype.h>
37#include <errno.h>
38#include <limits.h>
39#include <stdlib.h>
40
41/*
42 * Convert a string to a long long.
43 *
44 * Ignores `locale' stuff. Assumes that the upper and lower case
45 * alphabets and digits are each contiguous.
46 */
47long long
48strtoll(const char *nptr, char **endptr, int base)
49{
50 const char *s;
51 long long acc, cutoff;
52 int c;
53 int neg, any, cutlim;
54
55 /*
56 * Skip white space and pick up leading +/- sign if any.
57 * If base is 0, allow 0x for hex and 0 for octal, else
58 * assume decimal; if base is already 16, allow 0x.
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) &&
73 c == '0' && (*s == 'x' || *s == 'X')) {
74 c = s[1];
75 s += 2;
76 base = 16;
77 }
78 if (base == 0)
79 base = c == '0' ? 8 : 10;
80
81 /*
82 * Compute the cutoff value between legal numbers and illegal
83 * numbers. That is the largest legal value, divided by the
84 * base. An input number that is greater than this value, if
85 * followed by a legal input character, is too big. One that
86 * is equal to this value may be valid or not; the limit
87 * between valid and invalid numbers is then based on the last
88 * digit. For instance, if the range for long longs is
89 * [-9223372036854775808..9223372036854775807] and the input base
90 * is 10, cutoff will be set to 922337203685477580 and cutlim to
91 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
92 * accumulated a value > 922337203685477580, or equal but the
93 * next digit is > 7 (or 8), the number is too big, and we will
94 * return a range error.
95 *
96 * Set any if any `digits' consumed; make it negative to indicate
97 * overflow.
98 */
99 cutoff = neg ? LLONG_MIN : LLONG_MAX;
100 cutlim = cutoff % base;
101 cutoff /= base;
102 if (neg) {
103 if (cutlim > 0) {
104 cutlim -= base;
105 cutoff += 1;
106 }
107 cutlim = -cutlim;
108 }
109 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
110 if (isdigit(c))
111 c -= '0';
112 else if (isalpha(c))
113 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
114 else
115 break;
116 if (c >= base)
117 break;
118 if (any < 0)
119 continue;
120 if (neg) {
121 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
122 any = -1;
123 acc = LLONG_MIN;
124 errno = ERANGE;
125 } else {
126 any = 1;
127 acc *= base;
128 acc -= c;
129 }
130 } else {
131 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
132 any = -1;
133 acc = LLONG_MAX;
134 errno = ERANGE;
135 } else {
136 any = 1;
137 acc *= base;
138 acc += c;
139 }
140 }
141 }
142 if (endptr != 0)
143 *endptr = (char *) (any ? s - 1 : nptr);
144 return (acc);
145}
146
147#ifdef __weak_alias
148__weak_alias(strtoq, strtoll);
149#else
150quad_t
151strtoq(const char *nptr, char **endptr, int base)
152{
153
154 return ((quad_t)strtoll(nptr, endptr, base));
155}
156#endif
diff --git a/src/lib/libc/stdlib/strtonum.3 b/src/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000000..11910a627c
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,151 @@
1.\" $OpenBSD: strtonum.3,v 1.11 2005/04/14 07:58:46 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 April 29, 2004
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.Fd #include <stdlib.h>
25.Fd #include <limits.h>
26.Ft long long
27.Fo strtonum
28.Fa "const char *nptr"
29.Fa "long long minval"
30.Fa "long long maxval"
31.Fa "const char **errstr"
32.Fc
33.Sh DESCRIPTION
34The
35.Fn strtonum
36function converts the string in
37.Fa nptr
38to a
39.Li long long
40value.
41The
42.Fn strtonum
43function was designed to facilitate safe, robust programming
44and overcome the shortcomings of the
45.Xr atoi 3
46and
47.Xr strtol 3
48family of interfaces.
49.Pp
50The string may begin with an arbitrary amount of whitespace
51(as determined by
52.Xr isspace 3 )
53followed by a single optional
54.Ql +
55or
56.Ql -
57sign.
58.Pp
59The remainder of the string is converted to a
60.Li long long
61value according to base 10.
62.Pp
63The value obtained is then checked against the provided
64.Fa minval
65and
66.Fa maxval
67bounds.
68If
69.Fa errstr
70is non-null,
71.Fn strtonum
72stores an error string in
73.Fa *errstr
74indicating the failure.
75.Sh RETURN VALUES
76The
77.Fn strtonum
78function returns the result of the conversion,
79unless the value would exceed the provided bounds or is invalid.
80On error, 0 is returned and
81.Fa errstr
82will point to an error message.
83.Fa *errstr
84will be set to
85.Dv NULL
86on success;
87this fact can be used to differentiate
88a successful return of 0 from an error.
89.Sh EXAMPLES
90Using
91.Fn strtonum
92correctly is meant to be simpler than the alternative functions.
93.Bd -literal -offset indent
94int iterations;
95const char *errstr;
96
97iterations = strtonum(optarg, 1, 64, &errstr);
98if (errstr)
99 errx(1, "number of iterations is %s: %s", errstr, optarg);
100.Ed
101.Pp
102The above example will guarantee that the value of iterations is between
1031 and 64.
104.Sh ERRORS
105.Bl -tag -width Er
106.It Bq Er ERANGE
107The given string was out of range.
108.It Bq Er EINVAL
109The given string did not consist solely of digit characters.
110.It Bq Er EINVAL
111.Ar minval
112was larger than
113.Ar maxval .
114.El
115.Pp
116If an error occurs,
117.Fa errstr
118will be set to one of the following strings:
119.Pp
120.Bl -tag -width "too largeXX" -compact
121.It too large
122The result was larger than the provided maximum value.
123.It too small
124The result was smaller than the provided minimum value.
125.It invalid
126The string did not consist solely of digit characters.
127.El
128.Sh SEE ALSO
129.Xr atof 3 ,
130.Xr atoi 3 ,
131.Xr atol 3 ,
132.Xr atoll 3 ,
133.Xr sscanf 3 ,
134.Xr strtod 3 ,
135.Xr strtol 3 ,
136.Xr strtoul 3
137.Sh STANDARDS
138.Fn strtonum
139is an
140.Ox
141extension.
142The existing alternatives, such as
143.Xr atoi 3
144and
145.Xr strtol 3 ,
146are either impossible or difficult to use safely.
147.Sh HISTORY
148The
149.Fn strtonum
150function first appeared in
151.Ox 3.6 .
diff --git a/src/lib/libc/stdlib/strtonum.c b/src/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000000..e426388ed0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,65 @@
1/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert 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 char *ep;
34 int error = 0;
35 struct errval {
36 const char *errstr;
37 int err;
38 } ev[4] = {
39 { NULL, 0 },
40 { "invalid", EINVAL },
41 { "too small", ERANGE },
42 { "too large", ERANGE },
43 };
44
45 ev[0].err = errno;
46 errno = 0;
47 if (minval > maxval)
48 error = INVALID;
49 else {
50 ll = strtoll(numstr, &ep, 10);
51 if (numstr == ep || *ep != '\0')
52 error = INVALID;
53 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54 error = TOOSMALL;
55 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56 error = TOOLARGE;
57 }
58 if (errstrp != NULL)
59 *errstrp = ev[error].errstr;
60 errno = ev[error].err;
61 if (error)
62 ll = 0;
63
64 return (ll);
65}
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
new file mode 100644
index 0000000000..4f6d6a51f9
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,231 @@
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.15 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 25, 1992
35.Dt STRTOUL 3
36.Os
37.Sh NAME
38.Nm strtoul ,
39.Nm strtoull ,
40.Nm strtouq
41.Nd "convert a string to an unsigned long or unsigned long long integer"
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Fd #include <limits.h>
45.Ft unsigned long
46.Fn strtoul "const char *nptr" "char **endptr" "int base"
47.Pp
48.Fd #include <stdlib.h>
49.Fd #include <limits.h>
50.Ft unsigned long long
51.Fn strtoull "const char *nptr" "char **endptr" "int base"
52.Pp
53.Fd #include <sys/types.h>
54.Fd #include <stdlib.h>
55.Fd #include <limits.h>
56.Ft u_quad_t
57.Fn strtouq "const char *nptr" "char **endptr" "int base"
58.Sh DESCRIPTION
59The
60.Fn strtoul
61function converts the string in
62.Fa nptr
63to an
64.Li unsigned long
65value.
66The
67.Fn strtoull
68function converts the string in
69.Fa nptr
70to an
71.Li unsigned long long
72value.
73The
74.Fn strtouq
75function is a deprecated equivalent of
76.Fn strtoull
77and is provided for backwards compatibility with legacy programs.
78The conversion is done according to the given
79.Fa base ,
80which must be a number between 2 and 36 inclusive
81or the special value 0.
82If the string in
83.Fa nptr
84represents a negative number, it will be converted to its unsigned equivalent.
85This behavior is consistent with what happens when a signed integer type is
86cast to its unsigned counterpart.
87.Pp
88The string may begin with an arbitrary amount of whitespace
89(as determined by
90.Xr isspace 3 )
91followed by a single optional
92.Ql +
93or
94.Ql -
95sign.
96If
97.Fa base
98is zero or 16, the string may then include a
99.Ql 0x
100prefix, and the number will be read in base 16; otherwise, a zero
101.Fa base
102is taken as 10 (decimal) unless the next character is
103.Ql 0 ,
104in which case it is taken as 8 (octal).
105.Pp
106The remainder of the string is converted to an
107.Li unsigned long
108value in the obvious manner, stopping at the end of the string
109or at the first character that does not produce a valid digit
110in the given base.
111(In bases above 10, the letter
112.Ql A
113in either upper or lower case represents 10,
114.Ql B
115represents 11, and so forth, with
116.Ql Z
117representing 35.)
118.Pp
119If
120.Fa endptr
121is non-null,
122.Fn strtoul
123stores the address of the first invalid character in
124.Fa *endptr .
125If there were no digits at all, however,
126.Fn strtoul
127stores the original value of
128.Fa nptr
129in
130.Fa *endptr .
131(Thus, if
132.Fa *nptr
133is not
134.Ql \e0
135but
136.Fa **endptr
137is
138.Ql \e0
139on return, the entire string was valid.)
140.Sh RETURN VALUES
141The
142.Fn strtoul
143function returns the result of the conversion,
144unless the value would overflow, in which case
145.Dv ULONG_MAX
146is returned and
147.Va errno
148is set to
149.Er ERANGE .
150If there was a leading minus sign,
151.Fn strtoul
152returns the (unsigned) negation of the absolute value of the number, unless
153the absolute value would overflow.
154In this case,
155.Fn strtoul
156returns
157.Dv ULONG_MAX
158and sets the global variable
159.Va errno
160to
161.Er ERANGE .
162.Pp
163The
164.Fn strtoull
165function has identical return values except that
166.Dv ULLONG_MAX
167is used to indicate overflow.
168.Pp
169There is no way to determine if
170.Fn strtoul
171has processed a negative number (and returned an unsigned value) short of
172examining the string in
173.Fa nptr
174directly.
175.Sh EXAMPLES
176Ensuring that a string is a valid number (i.e., in range and containing no
177trailing characters) requires clearing
178.Va errno
179beforehand explicitly since
180.Va errno
181is not changed on a successful call to
182.Fn strtoul ,
183and the return value of
184.Fn strtoul
185cannot be used unambiguously to signal an error:
186.Bd -literal -offset indent
187char *ep;
188unsigned long ulval;
189
190\&...
191
192errno = 0;
193ulval = strtoul(buf, &ep, 10);
194if (buf[0] == '\e0' || *ep != '\e0')
195 goto not_a_number;
196if (errno == ERANGE && ulval == ULONG_MAX)
197 goto out_of_range;
198.Ed
199.Pp
200This example will accept
201.Dq 12
202but not
203.Dq 12foo
204or
205.Dq 12\en .
206If trailing whitespace is acceptable, further checks must be done on
207.Va *ep ;
208alternately, use
209.Xr sscanf 3 .
210.Sh ERRORS
211.Bl -tag -width Er
212.It Bq Er ERANGE
213The given string was out of range; the value converted has been clamped.
214.El
215.Sh SEE ALSO
216.Xr sscanf 3 ,
217.Xr strtol 3
218.Sh STANDARDS
219The
220.Fn strtoul
221and
222.Fn strtoull
223functions conform to
224.St -ansiC-99 .
225The
226.Fn strtouq
227function is a
228.Bx
229extension and is provided for backwards compatibility with legacy programs.
230.Sh BUGS
231Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
new file mode 100644
index 0000000000..1faa0abbd0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strtoul.c,v 1.6 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <ctype.h>
35#include <errno.h>
36#include <limits.h>
37#include <stdlib.h>
38
39/*
40 * Convert a string to an unsigned long integer.
41 *
42 * Ignores `locale' stuff. Assumes that the upper and lower case
43 * alphabets and digits are each contiguous.
44 */
45unsigned long
46strtoul(const char *nptr, char **endptr, int base)
47{
48 const char *s;
49 unsigned long acc, cutoff;
50 int c;
51 int neg, any, cutlim;
52
53 /*
54 * See strtol for comments as to the logic used.
55 */
56 s = nptr;
57 do {
58 c = (unsigned char) *s++;
59 } while (isspace(c));
60 if (c == '-') {
61 neg = 1;
62 c = *s++;
63 } else {
64 neg = 0;
65 if (c == '+')
66 c = *s++;
67 }
68 if ((base == 0 || base == 16) &&
69 c == '0' && (*s == 'x' || *s == 'X')) {
70 c = s[1];
71 s += 2;
72 base = 16;
73 }
74 if (base == 0)
75 base = c == '0' ? 8 : 10;
76
77 cutoff = ULONG_MAX / (unsigned long)base;
78 cutlim = ULONG_MAX % (unsigned long)base;
79 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
80 if (isdigit(c))
81 c -= '0';
82 else if (isalpha(c))
83 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
84 else
85 break;
86 if (c >= base)
87 break;
88 if (any < 0)
89 continue;
90 if (acc > cutoff || acc == cutoff && c > cutlim) {
91 any = -1;
92 acc = ULONG_MAX;
93 errno = ERANGE;
94 } else {
95 any = 1;
96 acc *= (unsigned long)base;
97 acc += c;
98 }
99 }
100 if (neg && any > 0)
101 acc = -acc;
102 if (endptr != 0)
103 *endptr = (char *) (any ? s - 1 : nptr);
104 return (acc);
105}
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000000..5fa841fff7
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,118 @@
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static const char rcsid[] = "$OpenBSD: strtoull.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35
36#include <ctype.h>
37#include <errno.h>
38#include <limits.h>
39#include <stdlib.h>
40
41/*
42 * Convert a string to an unsigned long long.
43 *
44 * Ignores `locale' stuff. Assumes that the upper and lower case
45 * alphabets and digits are each contiguous.
46 */
47unsigned long long
48strtoull(const char *nptr, char **endptr, int base)
49{
50 const char *s;
51 unsigned long long acc, cutoff;
52 int c;
53 int neg, any, cutlim;
54
55 /*
56 * See strtoq for comments as to the logic used.
57 */
58 s = nptr;
59 do {
60 c = (unsigned char) *s++;
61 } while (isspace(c));
62 if (c == '-') {
63 neg = 1;
64 c = *s++;
65 } else {
66 neg = 0;
67 if (c == '+')
68 c = *s++;
69 }
70 if ((base == 0 || base == 16) &&
71 c == '0' && (*s == 'x' || *s == 'X')) {
72 c = s[1];
73 s += 2;
74 base = 16;
75 }
76 if (base == 0)
77 base = c == '0' ? 8 : 10;
78
79 cutoff = ULLONG_MAX / (unsigned long long)base;
80 cutlim = ULLONG_MAX % (unsigned long long)base;
81 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
82 if (isdigit(c))
83 c -= '0';
84 else if (isalpha(c))
85 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
86 else
87 break;
88 if (c >= base)
89 break;
90 if (any < 0)
91 continue;
92 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
93 any = -1;
94 acc = ULLONG_MAX;
95 errno = ERANGE;
96 } else {
97 any = 1;
98 acc *= (unsigned long long)base;
99 acc += c;
100 }
101 }
102 if (neg && any > 0)
103 acc = -acc;
104 if (endptr != 0)
105 *endptr = (char *) (any ? s - 1 : nptr);
106 return (acc);
107}
108
109#ifdef __weak_alias
110__weak_alias(strtouq, strtoull);
111#else
112u_quad_t
113strtouq(const char *nptr, char **endptr, int base)
114{
115
116 return ((u_quad_t)strtoull(nptr, endptr, base));
117}
118#endif
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
new file mode 100644
index 0000000000..1034b01066
--- /dev/null
+++ b/src/lib/libc/stdlib/system.3
@@ -0,0 +1,99 @@
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.9 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt SYSTEM 3
36.Os
37.Sh NAME
38.Nm system
39.Nd pass a command to the shell
40.Sh SYNOPSIS
41.Fd #include <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.Sh RETURN VALUES
70If a child process cannot be created, or the termination status of
71the shell cannot be obtained,
72.Fn system
73returns \-1 and sets
74.Va errno
75to indicate the error.
76If execution of the shell fails,
77.Fn system
78returns the termination status for a program that terminates with a call of
79.Fn exit 127 .
80.Sh SEE ALSO
81.Xr sh 1 ,
82.Xr execve 2 ,
83.Xr waitpid 2 ,
84.Xr popen 3
85.Sh STANDARDS
86The
87.Fn system
88function conforms to
89.St -ansiC
90and
91.St -p1003.2-92 .
92.Sh CAVEATS
93Never supply the
94.Fn system
95function with a command containing any part of an unsanitized user-supplied
96string.
97Shell meta-characters present will be honored by the
98.Xr sh 1
99command interpreter.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
new file mode 100644
index 0000000000..ebf5577674
--- /dev/null
+++ b/src/lib/libc/stdlib/system.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: system.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <signal.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <paths.h>
40
41extern char **environ;
42
43int
44system(const char *command)
45{
46 pid_t pid;
47 sig_t intsave, quitsave;
48 sigset_t mask, omask;
49 int pstat;
50 char *argp[] = {"sh", "-c", NULL, NULL};
51
52 if (!command) /* just checking... */
53 return(1);
54
55 argp[2] = (char *)command;
56
57 sigemptyset(&mask);
58 sigaddset(&mask, SIGCHLD);
59 sigprocmask(SIG_BLOCK, &mask, &omask);
60 switch (pid = vfork()) {
61 case -1: /* error */
62 sigprocmask(SIG_SETMASK, &omask, NULL);
63 return(-1);
64 case 0: /* child */
65 sigprocmask(SIG_SETMASK, &omask, NULL);
66 execve(_PATH_BSHELL, argp, environ);
67 _exit(127);
68 }
69
70 intsave = signal(SIGINT, SIG_IGN);
71 quitsave = signal(SIGQUIT, SIG_IGN);
72 pid = waitpid(pid, (int *)&pstat, 0);
73 sigprocmask(SIG_SETMASK, &omask, NULL);
74 (void)signal(SIGINT, intsave);
75 (void)signal(SIGQUIT, quitsave);
76 return (pid == -1 ? -1 : pstat);
77}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..ff6bcd742d
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/* $OpenBSD: tfind.c,v 1.5 2005/03/30 18:51:49 pat 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, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14#include <search.h>
15
16typedef struct node_t
17{
18 char *key;
19 struct node_t *llink, *rlink;
20} node;
21
22/* find a node, or return 0 */
23void *
24tfind(const void *vkey, void * const *vrootp,
25 int (*compar)(const void *, const void *))
26{
27 char *key = (char *)vkey;
28 node **rootp = (node **)vrootp;
29
30 if (rootp == (struct node_t **)0)
31 return ((struct node_t *)0);
32 while (*rootp != (struct node_t *)0) { /* T1: */
33 int r;
34 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
35 return (*rootp); /* key found */
36 rootp = (r < 0) ?
37 &(*rootp)->llink : /* T3: follow left branch */
38 &(*rootp)->rlink; /* T4: follow right branch */
39 }
40 return (node *)0;
41}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000000..15d7b84a3a
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,116 @@
1.\" $OpenBSD: tsearch.3,v 1.12 2003/06/17 21:56:24 millert Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd June 15, 1997
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.Fd #include <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.
71It takes the same arguments as
72.Fn tfind
73and
74.Fn tsearch .
75If the node to be deleted is the root of the binary search tree,
76.Fa rootp
77will be adjusted.
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 tfind ,
100.Fn tsearch ,
101and
102.Fn tdelete
103return
104.Dv NULL
105if
106.Fa rootp
107is
108.Dv NULL
109or the datum cannot be found.
110.Pp
111The
112.Fn twalk
113function returns no value.
114.Sh SEE ALSO
115.Xr bsearch 3 ,
116.Xr lsearch 3
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..a5d0c2b9b3
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
1/* $OpenBSD: tsearch.c,v 1.5 2005/03/30 18:51:49 pat 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, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14
15#include <search.h>
16#include <stdlib.h>
17
18typedef struct node_t {
19 char *key;
20 struct node_t *left, *right;
21} node;
22
23/* find or insert datum into search tree */
24void *
25tsearch(const void *vkey, void **vrootp,
26 int (*compar)(const void *, const void *))
27{
28 node *q;
29 char *key = (char *)vkey;
30 node **rootp = (node **)vrootp;
31
32 if (rootp == (struct node_t **)0)
33 return ((void *)0);
34 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
35 int r;
36
37 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
38 return ((void *)*rootp); /* we found it! */
39 rootp = (r < 0) ?
40 &(*rootp)->left : /* T3: follow left branch */
41 &(*rootp)->right; /* T4: follow right branch */
42 }
43 q = (node *) malloc(sizeof(node)); /* T5: key not found */
44 if (q != (struct node_t *)0) { /* make new node */
45 *rootp = q; /* link new node to old */
46 q->key = key; /* initialize new node */
47 q->left = q->right = (struct node_t *)0;
48 }
49 return ((void *)q);
50}
51
52/* delete node with given key */
53void *
54tdelete(const void *vkey, void **vrootp,
55 int (*compar)(const void *, const void *))
56{
57 node **rootp = (node **)vrootp;
58 char *key = (char *)vkey;
59 node *p;
60 node *q;
61 node *r;
62 int cmp;
63
64 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
65 return ((struct node_t *)0);
66 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
67 p = *rootp;
68 rootp = (cmp < 0) ?
69 &(*rootp)->left : /* follow left branch */
70 &(*rootp)->right; /* follow right branch */
71 if (*rootp == (struct node_t *)0)
72 return ((void *)0); /* key not found */
73 }
74 r = (*rootp)->right; /* D1: */
75 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
76 q = r;
77 else if (r != (struct node_t *)0) { /* Right link is null? */
78 if (r->left == (struct node_t *)0) { /* D2: Find successor */
79 r->left = q;
80 q = r;
81 } else { /* D3: Find (struct node_t *)0 link */
82 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
83 r = q;
84 r->left = q->right;
85 q->left = (*rootp)->left;
86 q->right = (*rootp)->right;
87 }
88 }
89 free((struct node_t *) *rootp); /* D4: Free node */
90 *rootp = q; /* link parent to new node */
91 return(p);
92}
93
94/* Walk the nodes of a tree */
95static void
96trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
97{
98 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
99 (*action)(root, leaf, level);
100 else {
101 (*action)(root, preorder, level);
102 if (root->left != (struct node_t *)0)
103 trecurse(root->left, action, level + 1);
104 (*action)(root, postorder, level);
105 if (root->right != (struct node_t *)0)
106 trecurse(root->right, action, level + 1);
107 (*action)(root, endorder, level);
108 }
109}
110
111/* Walk the nodes of a tree */
112void
113twalk(const void *vroot, void (*action)(const void *, VISIT, int))
114{
115 node *root = (node *)vroot;
116
117 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
118 trecurse(root, action, 0);
119}
diff --git a/src/lib/libc/string/Makefile.inc b/src/lib/libc/string/Makefile.inc
new file mode 100644
index 0000000000..8150294d1c
--- /dev/null
+++ b/src/lib/libc/string/Makefile.inc
@@ -0,0 +1,177 @@
1# $OpenBSD: Makefile.inc,v 1.16 2005/04/16 12:26:12 jmc Exp $
2
3# string sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string ${LIBCSRCDIR}/string
5
6SRCS+= bm.c memccpy.c strcasecmp.c strcasestr.c strcoll.c strdup.c \
7 strerror.c strerror_r.c strlcat.c strmode.c strsignal.c strtok.c \
8 strxfrm.c __strsignal.c \
9 wcscat.c wcschr.c wcscmp.c wcscpy.c wcscspn.c wcslcat.c wcslcpy.c \
10 wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c wcsrchr.c wcsspn.c \
11 wcsstr.c wcstok.c wcswcs.c wmemchr.c wmemcmp.c wmemcpy.c \
12 wmemmove.c wmemset.c
13
14# machine-dependent net sources
15# m-d Makefile.inc must include sources for:
16# bcmp() bcopy() bzero() ffs() index() memchr() memcmp() memset()
17# rindex() strcat() strcmp() strcpy() strcspn() strlen() strlcpy()
18# strncat() strncmp() strncpy() strpbrk() strsep()
19# strspn() strstr() swav()
20# m-d Makefile.inc may include sources for:
21# memcpy() memmove() strchr() strrchr()
22
23.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc"
24
25# if no machine specific memmove(3), build one out of bcopy(3).
26.if empty(SRCS:Mmemmove.S)
27OBJS+= memmove.o
28memmove.o: bcopy.c
29 ${CC} -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
30 @${LD} -x -r ${.TARGET}
31 @mv a.out ${.TARGET}
32
33memmove.go: bcopy.c
34 ${CC} -g -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
35 @${LD} -x -r ${.TARGET}
36 @mv a.out ${.TARGET}
37
38memmove.po: bcopy.c
39 ${CC} -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
40 @${LD} -X -r ${.TARGET}
41 @mv a.out ${.TARGET}
42
43memmove.so: bcopy.c
44 ${CC} ${PICFLAG} -DPIC -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} \
45 -o ${.TARGET}
46.endif
47
48# if no machine specific memcpy(3), build one out of bcopy(3).
49# if there is a machine specific memmove(3), we'll assume it aliases
50# memcpy(3).
51.if empty(SRCS:Mmemcpy.S)
52.if empty(SRCS:Mmemmove.S)
53OBJS+= memcpy.o
54memcpy.o: bcopy.c
55 ${CC} -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
56 @${LD} -x -r ${.TARGET}
57 @mv a.out ${.TARGET}
58
59memcpy.go: bcopy.c
60 ${CC} -g -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
61 @${LD} -x -r ${.TARGET}
62 @mv a.out ${.TARGET}
63
64memcpy.po: bcopy.c
65 ${CC} -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
66 @${LD} -X -r ${.TARGET}
67 @mv a.out ${.TARGET}
68
69memcpy.so: bcopy.c
70 ${CC} ${PICFLAG} -DPIC -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} \
71 -o ${.TARGET}
72.endif
73.endif
74
75# if no machine specific strchr(3), build one out of index(3).
76.if empty(SRCS:Mstrchr.S)
77OBJS+= strchr.o
78strchr.o: index.c
79 ${CC} -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
80 @${LD} -x -r ${.TARGET}
81 @mv a.out ${.TARGET}
82
83strchr.go: index.c
84 ${CC} -g -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
85 @${LD} -x -r ${.TARGET}
86 @mv a.out ${.TARGET}
87
88strchr.po: index.c
89 ${CC} -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
90 @${LD} -X -r ${.TARGET}
91 @mv a.out ${.TARGET}
92
93strchr.so: index.c
94 ${CC} ${PICFLAG} -DPIC -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} \
95 -o ${.TARGET}
96.endif
97
98# if no machine specific strrchr(3), build one out of rindex(3).
99.if empty(SRCS:Mstrrchr.S)
100OBJS+= strrchr.o
101strrchr.o: rindex.c
102 ${CC} -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
103 @${LD} -x -r ${.TARGET}
104 @mv a.out ${.TARGET}
105
106strrchr.go: rindex.c
107 ${CC} -g -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
108 @${LD} -x -r ${.TARGET}
109 @mv a.out ${.TARGET}
110
111strrchr.po: rindex.c
112 ${CC} -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
113 @${LD} -X -r ${.TARGET}
114 @mv a.out ${.TARGET}
115
116strrchr.so: rindex.c
117 ${CC} ${PICFLAG} -DPIC -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} \
118 -o ${.TARGET}
119.endif
120
121# build .ln files for memmove, memcpy, strchr and strrchr always from
122# bcopy, index, and rindex
123LOBJS+= memmove.ln memcpy.ln strchr.ln strrchr.ln
124
125memmove.ln: bcopy.c
126 lint ${LINTFLAGS} -DMEMMOVE ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
127 ${LIBCSRCDIR}/string/bcopy.c
128
129memcpy.ln: bcopy.c
130 lint ${LINTFLAGS} -DMEMCOPY ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
131 ${LIBCSRCDIR}/string/bcopy.c
132
133strchr.ln: index.c
134 lint ${LINTFLAGS} -DSTRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
135 ${LIBCSRCDIR}/string/index.c
136
137strrchr.ln: rindex.c
138 lint ${LINTFLAGS} -DSTRRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
139 ${LIBCSRCDIR}/string/rindex.c
140
141MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 memccpy.3 memchr.3 \
142 memcmp.3 memcpy.3 memmove.3 memset.3 strcasecmp.3 strcat.3 \
143 strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strerror.3 \
144 string.3 strlen.3 strmode.3 strdup.3 strpbrk.3 strrchr.3 strsep.3 \
145 strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 strlcpy.3 \
146 wcstok.3 wmemchr.3
147
148MLINKS+=bm.3 bm_comp.3 bm.3 bm_exec.3 bm.3 bm_free.3
149MLINKS+=strchr.3 index.3
150MLINKS+=strrchr.3 rindex.3
151MLINKS+=strcasecmp.3 strncasecmp.3
152MLINKS+=strcat.3 strncat.3
153MLINKS+=strcmp.3 strncmp.3
154MLINKS+=strcpy.3 strncpy.3
155MLINKS+=strlcpy.3 strlcat.3
156MLINKS+=strstr.3 strcasestr.3
157MLINKS+=strtok.3 strtok_r.3
158MLINKS+=strerror.3 strerror_r.3
159MLINKS+=wmemchr.3 wmemcmp.3
160MLINKS+=wmemchr.3 wmemcpy.3
161MLINKS+=wmemchr.3 wmemmove.3
162MLINKS+=wmemchr.3 wmemset.3
163MLINKS+=wmemchr.3 wcscat.3
164MLINKS+=wmemchr.3 wcschr.3
165MLINKS+=wmemchr.3 wcscmp.3
166MLINKS+=wmemchr.3 wcscpy.3
167MLINKS+=wmemchr.3 wcscspn.3
168MLINKS+=wmemchr.3 wcslcat.3
169MLINKS+=wmemchr.3 wcslcpy.3
170MLINKS+=wmemchr.3 wcslen.3
171MLINKS+=wmemchr.3 wcsncat.3
172MLINKS+=wmemchr.3 wcsncmp.3
173MLINKS+=wmemchr.3 wcsncpy.3
174MLINKS+=wmemchr.3 wcspbrk.3
175MLINKS+=wmemchr.3 wcsrchr.3
176MLINKS+=wmemchr.3 wcsspn.3
177MLINKS+=wmemchr.3 wcsstr.3
diff --git a/src/lib/libc/string/__strsignal.c b/src/lib/libc/string/__strsignal.c
new file mode 100644
index 0000000000..ebbf08d24a
--- /dev/null
+++ b/src/lib/libc/string/__strsignal.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: __strsignal.c,v 1.9 2005/03/30 20:13:52 otto Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#ifdef NLS
35#define catclose _catclose
36#define catgets _catgets
37#define catopen _catopen
38#include <nl_types.h>
39#endif
40
41#define sys_siglist _sys_siglist
42
43#include <stdio.h>
44#include <limits.h>
45#include <signal.h>
46#include <string.h>
47
48static char *itoa(int num)
49{
50 static char buffer[11];
51 char *p;
52
53 p = buffer + 4;
54 while (num >= 10) {
55 *--p = (num % 10) + '0';
56 num /= 10;
57 }
58 *p = (num % 10) + '0';
59 return p;
60}
61
62char *
63__strsignal(int num, char *buf)
64{
65#define UPREFIX "Unknown signal: "
66 unsigned int signum;
67
68#ifdef NLS
69 nl_catd catd ;
70 catd = catopen("libc", 0);
71#endif
72
73 signum = num; /* convert to unsigned */
74 if (signum < NSIG) {
75#ifdef NLS
76 strlcpy(buf, catgets(catd, 2, signum,
77 (char *)sys_siglist[signum]), NL_TEXTMAX);
78#else
79 return((char *)sys_siglist[signum]);
80#endif
81 } else {
82#ifdef NLS
83 strlcpy(buf, catgets(catd, 1, 0xffff, UPREFIX), NL_TEXTMAX);
84#else
85 strlcpy(buf, UPREFIX, NL_TEXTMAX);
86#endif
87 strlcat(buf, itoa(signum), NL_TEXTMAX);
88 }
89
90#ifdef NLS
91 catclose(catd);
92#endif
93
94 return buf;
95}
diff --git a/src/lib/libc/string/bcmp.3 b/src/lib/libc/string/bcmp.3
new file mode 100644
index 0000000000..953476caa7
--- /dev/null
+++ b/src/lib/libc/string/bcmp.3
@@ -0,0 +1,66 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
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: bcmp.3,v 1.6 2003/06/02 20:18:38 millert Exp $
31.\"
32.Dd April 19, 1991
33.Dt BCMP 3
34.Os
35.Sh NAME
36.Nm bcmp
37.Nd compare byte string
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft int
41.Fn bcmp "const void *b1" "const void *b2" "size_t len"
42.Sh DESCRIPTION
43The
44.Fn bcmp
45function compares byte string
46.Fa b1
47against byte string
48.Fa b2 ,
49returning zero if they are identical, non-zero otherwise.
50Both strings are assumed to be
51.Fa len
52bytes long.
53Zero-length strings are always identical.
54.Pp
55The strings may overlap.
56.Sh SEE ALSO
57.Xr memcmp 3 ,
58.Xr strcasecmp 3 ,
59.Xr strcmp 3 ,
60.Xr strcoll 3 ,
61.Xr strxfrm 3
62.Sh HISTORY
63A
64.Fn bcmp
65function first appeared in
66.Bx 4.2 .
diff --git a/src/lib/libc/string/bcmp.c b/src/lib/libc/string/bcmp.c
new file mode 100644
index 0000000000..07d32ed043
--- /dev/null
+++ b/src/lib/libc/string/bcmp.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: bcmp.c,v 1.7 2005/03/30 20:13:52 otto Exp $ */
2
3/*
4 * Copyright (c) 1987 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: bcmp.c,v 1.7 2005/03/30 20:13:52 otto Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42/*
43 * bcmp -- vax cmpc3 instruction
44 */
45int
46bcmp(const void *b1, const void *b2, size_t length)
47{
48 char *p1, *p2;
49
50 if (length == 0)
51 return(0);
52 p1 = (char *)b1;
53 p2 = (char *)b2;
54 do
55 if (*p1++ != *p2++)
56 break;
57 while (--length);
58 return(length);
59}
diff --git a/src/lib/libc/string/bcopy.3 b/src/lib/libc/string/bcopy.3
new file mode 100644
index 0000000000..7b55bcbf43
--- /dev/null
+++ b/src/lib/libc/string/bcopy.3
@@ -0,0 +1,67 @@
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.\"
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: bcopy.3,v 1.8 2003/06/21 12:04:01 avsm Exp $
32.\"
33.Dd April 19, 1991
34.Dt BCOPY 3
35.Os
36.Sh NAME
37.Nm bcopy
38.Nd copy bytes
39.Sh SYNOPSIS
40.Fd #include <string.h>
41.Ft void
42.Fn bcopy "const void *src" "void *dst" "size_t len"
43.Sh DESCRIPTION
44The
45.Fn bcopy
46function copies
47.Fa len
48bytes from buffer
49.Fa src
50to buffer
51.Fa dst .
52The two buffers may overlap.
53If
54.Fa len
55is zero, no bytes are copied.
56.Sh SEE ALSO
57.Xr memccpy 3 ,
58.Xr memcpy 3 ,
59.Xr memmove 3 ,
60.Xr strcpy 3 ,
61.Xr strlcpy 3 ,
62.Xr strncpy 3
63.Sh HISTORY
64A
65.Fn bcopy
66function appeared in
67.Bx 4.2 .
diff --git a/src/lib/libc/string/bcopy.c b/src/lib/libc/string/bcopy.c
new file mode 100644
index 0000000000..7b30ab4abb
--- /dev/null
+++ b/src/lib/libc/string/bcopy.c
@@ -0,0 +1,131 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: bcopy.c,v 1.4 2005/03/30 20:13:52 otto Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * sizeof(word) MUST BE A POWER OF TWO
41 * SO THAT wmask BELOW IS ALL ONES
42 */
43typedef long word; /* "word" used for optimal copy speed */
44
45#define wsize sizeof(word)
46#define wmask (wsize - 1)
47
48/*
49 * Copy a block of memory, handling overlap.
50 * This is the routine that actually implements
51 * (the portable versions of) bcopy, memcpy, and memmove.
52 */
53#ifdef MEMCOPY
54void *
55memcpy(void *dst0, const void *src0, size_t length)
56#else
57#ifdef MEMMOVE
58void *
59memmove(void *dst0, const void *src0, size_t length)
60#else
61void
62bcopy(const void *src0, void *dst0, size_t length)
63#endif
64#endif
65{
66 char *dst = dst0;
67 const char *src = src0;
68 size_t t;
69
70 if (length == 0 || dst == src) /* nothing to do */
71 goto done;
72
73 /*
74 * Macros: loop-t-times; and loop-t-times, t>0
75 */
76#define TLOOP(s) if (t) TLOOP1(s)
77#define TLOOP1(s) do { s; } while (--t)
78
79 if ((unsigned long)dst < (unsigned long)src) {
80 /*
81 * Copy forward.
82 */
83 t = (long)src; /* only need low bits */
84 if ((t | (long)dst) & wmask) {
85 /*
86 * Try to align operands. This cannot be done
87 * unless the low bits match.
88 */
89 if ((t ^ (long)dst) & wmask || length < wsize)
90 t = length;
91 else
92 t = wsize - (t & wmask);
93 length -= t;
94 TLOOP1(*dst++ = *src++);
95 }
96 /*
97 * Copy whole words, then mop up any trailing bytes.
98 */
99 t = length / wsize;
100 TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
101 t = length & wmask;
102 TLOOP(*dst++ = *src++);
103 } else {
104 /*
105 * Copy backwards. Otherwise essentially the same.
106 * Alignment works as before, except that it takes
107 * (t&wmask) bytes to align, not wsize-(t&wmask).
108 */
109 src += length;
110 dst += length;
111 t = (long)src;
112 if ((t | (long)dst) & wmask) {
113 if ((t ^ (long)dst) & wmask || length <= wsize)
114 t = length;
115 else
116 t &= wmask;
117 length -= t;
118 TLOOP1(*--dst = *--src);
119 }
120 t = length / wsize;
121 TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
122 t = length & wmask;
123 TLOOP(*--dst = *--src);
124 }
125done:
126#if defined(MEMCOPY) || defined(MEMMOVE)
127 return (dst0);
128#else
129 return;
130#endif
131}
diff --git a/src/lib/libc/string/bm.3 b/src/lib/libc/string/bm.3
new file mode 100644
index 0000000000..772b0d372e
--- /dev/null
+++ b/src/lib/libc/string/bm.3
@@ -0,0 +1,111 @@
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.\" Andrew Hume of AT&T Bell Laboratories.
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: bm.3,v 1.7 2003/06/02 20:18:38 millert Exp $
32.\"
33.Dd June 29, 1999
34.Dt BM 3
35.Os
36.Sh NAME
37.Nm bm_comp ,
38.Nm bm_exec ,
39.Nm bm_free
40.Nd Boyer-Moore string search
41.Sh SYNOPSIS
42.Fd #include <sys/types.h>
43.Fd #include <bm.h>
44.Ft bm_pat *
45.Fn bm_comp "u_char *pattern" "size_t patlen" "u_char freq[256]"
46.Ft u_char *
47.Fn bm_exec "bm_pat *pdesc" "u_char *text" "size_t len"
48.Ft void
49.Fn bm_free "bm_pat *pdesc"
50.Sh DESCRIPTION
51These routines implement an efficient mechanism to find an
52occurrence of a byte string within another byte string.
53.Pp
54.Fn bm_comp
55evaluates
56.Fa patlen
57bytes starting at
58.Fa pattern
59and returns a pointer to a structure describing them.
60The bytes referenced by
61.Fa pattern
62may be of any value.
63.Pp
64The search takes advantage of the frequency distribution of the
65bytes in the text to be searched.
66If specified,
67.Ar freq
68should be an array of 256 values,
69with higher values indicating that the corresponding character occurs
70more frequently.
71(A less than optimal frequency distribution can only result in less
72than optimal performance, not incorrect results.)
73If
74.Ar freq
75is
76.Dv NULL ,
77a system default table is used.
78.Pp
79.Fn bm_exec
80returns a pointer to the leftmost occurrence of the string given to
81.Fn bm_comp
82within
83.Ar text ,
84or
85.Dv NULL
86if none occurs.
87The number of bytes in
88.Ar text
89must be specified by
90.Ar len .
91.Pp
92Space allocated for the returned description is discarded
93by calling
94.Fn bm_free
95with the returned description as an argument.
96.Pp
97The asymptotic speed of
98.Fn bm_exec
99is
100.Pf O Ns Pq len / patlen .
101.Sh SEE ALSO
102.Xr regexp 3 ,
103.Xr strstr 3
104.Rs
105.%R "Fast String Searching"
106.%A Andrew Hume
107.%A Daniel Sunday
108.%J "Software Practice and Experience"
109.%V Volume 21, 11 (November 1991)
110.%P 1221-48
111.Re
diff --git a/src/lib/libc/string/bm.c b/src/lib/libc/string/bm.c
new file mode 100644
index 0000000000..6c8e4c3472
--- /dev/null
+++ b/src/lib/libc/string/bm.c
@@ -0,0 +1,208 @@
1/*-
2 * Copyright (c) 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Andrew Hume of AT&T Bell Laboratories.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: bm.c,v 1.5 2005/03/30 20:13:52 otto Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/types.h>
38
39#include <bm.h>
40#include <errno.h>
41#include <stdlib.h>
42#include <string.h>
43
44/*
45 * XXX
46 * The default frequency table starts at 99 and counts down. The default
47 * table should probably be oriented toward text, and will necessarily be
48 * locale specific. This one is for English. It was derived from the
49 * OSF/1 and 4.4BSD formatted and unformatted manual pages, and about 100Mb
50 * of email and random text. Change it if you can find something better.
51 */
52static u_char const freq_def[256] = {
53 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 77, 90, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0,
57 99, 28, 42, 27, 16, 14, 20, 51,
58 66, 65, 59, 24, 75, 76, 84, 56,
59 72, 74, 64, 55, 54, 47, 41, 37,
60 44, 61, 70, 43, 23, 53, 49, 22,
61 33, 58, 40, 46, 45, 57, 60, 26,
62 30, 63, 21, 12, 32, 50, 38, 39,
63 34, 11, 48, 67, 62, 35, 15, 29,
64 71, 18, 9, 17, 25, 13, 10, 52,
65 36, 95, 78, 86, 87, 98, 82, 80,
66 88, 94, 19, 68, 89, 83, 93, 96,
67 81, 7, 91, 92, 97, 85, 69, 73,
68 31, 79, 8, 5, 4, 6, 3, 0,
69 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0,
85};
86
87bm_pat *
88bm_comp(u_char const *pb, size_t len, u_char const *freq)
89{
90 u_char const *pe, *p;
91 size_t *d, r;
92 int j;
93 int sv_errno;
94 bm_pat *pat;
95
96 if (len == 0) {
97 errno = EINVAL;
98 return (NULL);
99 }
100 if ((pat = malloc(sizeof(*pat))) == NULL)
101 return (NULL);
102 pat->pat = NULL;
103 pat->delta = NULL;
104
105 pat->patlen = len; /* copy pattern */
106 if ((pat->pat = malloc(pat->patlen)) == NULL)
107 goto mem;
108 memcpy(pat->pat, pb, pat->patlen);
109 /* get skip delta */
110 if ((pat->delta = malloc(256 * sizeof(*d))) == NULL)
111 goto mem;
112 for (j = 0, d = pat->delta; j < 256; j++)
113 d[j] = pat->patlen;
114 for (pe = pb + pat->patlen - 1; pb <= pe; pb++)
115 d[*pb] = pe - pb;
116
117 if (freq == NULL) /* default freq table */
118 freq = freq_def;
119 r = 0; /* get guard */
120 for (pb = pat->pat, pe = pb + pat->patlen - 1; pb < pe; pb++)
121 if (freq[*pb] < freq[pat->pat[r]])
122 r = pb - pat->pat;
123 pat->rarec = pat->pat[r];
124 pat->rareoff = r - (pat->patlen - 1);
125
126 /* get md2 shift */
127 for (pe = pat->pat + pat->patlen - 1, p = pe - 1; p >= pat->pat; p--)
128 if (*p == *pe)
129 break;
130
131 /* *p is first leftward reoccurrence of *pe */
132 pat->md2 = pe - p;
133 return (pat);
134
135mem: sv_errno = errno;
136 bm_free(pat);
137 errno = sv_errno;
138 return (NULL);
139}
140
141void
142bm_free(bm_pat *pat)
143{
144 if (pat->pat != NULL)
145 free(pat->pat);
146 if (pat->delta != NULL)
147 free(pat->delta);
148 free(pat);
149}
150
151u_char *
152bm_exec(bm_pat *pat, u_char *base, size_t n)
153{
154 u_char *e, *ep, *p, *q, *s;
155 size_t *d0, k, md2, n1, ro;
156 int rc;
157
158 if (n == 0)
159 return (NULL);
160
161 d0 = pat->delta;
162 n1 = pat->patlen - 1;
163 md2 = pat->md2;
164 ro = pat->rareoff;
165 rc = pat->rarec;
166 ep = pat->pat + pat->patlen - 1;
167 s = base + (pat->patlen - 1);
168
169 /* fast loop up to n - 3 * patlen */
170 e = base + n - 3 * pat->patlen;
171 while (s < e) {
172 k = d0[*s]; /* ufast skip loop */
173 while (k) {
174 k = d0[*(s += k)];
175 k = d0[*(s += k)];
176 }
177 if (s >= e)
178 break;
179 if (s[ro] != rc) /* guard test */
180 goto mismatch1;
181 /* fwd match */
182 for (p = pat->pat, q = s - n1; p < ep;)
183 if (*q++ != *p++)
184 goto mismatch1;
185 return (s - n1);
186
187mismatch1: s += md2; /* md2 shift */
188 }
189
190 /* slow loop up to end */
191 e = base + n;
192 while (s < e) {
193 s += d0[*s]; /* step */
194 if (s >= e)
195 break;
196 if (s[ro] != rc) /* guard test */
197 goto mismatch2;
198 /* fwd match */
199 for (p = pat->pat, q = s - n1; p <= ep;)
200 if (*q++ != *p++)
201 goto mismatch2;
202 return (s - n1);
203
204mismatch2: s += md2; /* md2 shift */
205 }
206
207 return (NULL);
208}
diff --git a/src/lib/libc/string/bstring.3 b/src/lib/libc/string/bstring.3
new file mode 100644
index 0000000000..bcb5ac98fc
--- /dev/null
+++ b/src/lib/libc/string/bstring.3
@@ -0,0 +1,98 @@
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: bstring.3,v 1.7 2005/02/25 03:12:44 cloder Exp $
31.\"
32.Dd April 19, 1991
33.Dt BSTRING 3
34.Os
35.Sh NAME
36.Nm bstring
37.Nd byte string operations
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft int
41.Fn bcmp "const void *b1" "const void *b2" "size_t len"
42.Ft void
43.Fn bcopy "const void *src" "void *dst" "size_t len"
44.Ft void
45.Fn bzero "void *b" "size_t len"
46.Ft void *
47.Fn memchr "const void *b" "int c" "size_t len"
48.Ft int
49.Fn memcmp "const void *b1" "const void *b2" "size_t len"
50.Ft void *
51.Fn memccpy "void *dst" "const void *src" "int c" "size_t len"
52.Ft void *
53.Fn memcpy "void *dst" "const void *src" "size_t len"
54.Ft void *
55.Fn memmove "void *dst" "const void *src" "size_t len"
56.Ft void *
57.Fn memset "void *b" "int c" "size_t len"
58.Sh DESCRIPTION
59These functions operate on variable length strings of bytes.
60They do not check for terminating NUL bytes as the routines
61listed in
62.Xr string 3
63do.
64.Pp
65See the specific manual pages for more information.
66.Sh SEE ALSO
67.Xr bcmp 3 ,
68.Xr bcopy 3 ,
69.Xr bzero 3 ,
70.Xr memccpy 3 ,
71.Xr memchr 3 ,
72.Xr memcmp 3 ,
73.Xr memcpy 3 ,
74.Xr memmove 3 ,
75.Xr memset 3
76.Sh STANDARDS
77The functions
78.Fn memchr ,
79.Fn memcmp ,
80.Fn memcpy ,
81.Fn memmove ,
82and
83.Fn memset
84conform to
85.St -ansiC .
86.Sh HISTORY
87The
88.Fn bzero
89and
90.Fn memccpy
91functions appeared in
92.Bx 4.3 .
93The
94.Fn bcmp
95and
96.Fn bcopy
97functions appeared in
98.Bx 4.2 .
diff --git a/src/lib/libc/string/bzero.3 b/src/lib/libc/string/bzero.3
new file mode 100644
index 0000000000..592d9f2f08
--- /dev/null
+++ b/src/lib/libc/string/bzero.3
@@ -0,0 +1,61 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
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: bzero.3,v 1.6 2003/06/02 20:18:38 millert Exp $
31.\"
32.Dd April 19, 1991
33.Dt BZERO 3
34.Os
35.Sh NAME
36.Nm bzero
37.Nd write zeroes to a byte string
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft void
41.Fn bzero "void *b" "size_t len"
42.Sh DESCRIPTION
43The
44.Fn bzero
45function writes
46.Fa len
47zero bytes to the string
48.Fa b .
49If
50.Fa len
51is zero,
52.Fn bzero
53does nothing.
54.Sh SEE ALSO
55.Xr memset 3 ,
56.Xr swab 3
57.Sh HISTORY
58A
59.Fn bzero
60function appeared in
61.Bx 4.3 .
diff --git a/src/lib/libc/string/bzero.c b/src/lib/libc/string/bzero.c
new file mode 100644
index 0000000000..9d8a2cef3a
--- /dev/null
+++ b/src/lib/libc/string/bzero.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: bzero.c,v 1.6 2004/11/28 07:16:54 mickey Exp $ */
2
3/*
4 * Copyright (c) 1987 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: bzero.c,v 1.6 2004/11/28 07:16:54 mickey Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42/*
43 * bzero -- vax movc5 instruction
44 */
45void
46bzero(void *b, size_t length)
47{
48 char *p;
49
50 for (p = b; length--;)
51 *p++ = '\0';
52}
diff --git a/src/lib/libc/string/ffs.3 b/src/lib/libc/string/ffs.3
new file mode 100644
index 0000000000..a2f0cd336d
--- /dev/null
+++ b/src/lib/libc/string/ffs.3
@@ -0,0 +1,56 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" 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: ffs.3,v 1.4 2003/06/02 20:18:38 millert Exp $
31.\"
32.Dd April 19, 1991
33.Dt FFS 3
34.Os
35.Sh NAME
36.Nm ffs
37.Nd find first bit set in a bit string
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft int
41.Fn ffs "int value"
42.Sh DESCRIPTION
43The
44.Fn ffs
45function finds the first bit set in
46.Fa value
47and returns the index of that bit.
48Bits are numbered starting from 1, starting at the rightmost bit.
49A return value of 0 means that the argument was zero.
50.Sh SEE ALSO
51.Xr bitstring 3
52.Sh HISTORY
53The
54.Fn ffs
55function appeared in
56.Bx 4.3 .
diff --git a/src/lib/libc/string/ffs.c b/src/lib/libc/string/ffs.c
new file mode 100644
index 0000000000..f1d14096a2
--- /dev/null
+++ b/src/lib/libc/string/ffs.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: ffs.c,v 1.6 2003/06/11 21:08:16 deraadt Exp $ */
2
3/*
4 * Public domain.
5 * Written by Dale Rahn.
6 */
7
8#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$OpenBSD: ffs.c,v 1.6 2003/06/11 21:08:16 deraadt Exp $";
10#endif /* LIBC_SCCS and not lint */
11
12#if !defined(_KERNEL) && !defined(_STANDALONE)
13#include <string.h>
14#else
15#include <lib/libkern/libkern.h>
16#endif
17
18/*
19 * ffs -- vax ffs instruction
20 */
21int
22ffs(int mask)
23{
24 int bit;
25 unsigned int r = mask;
26 static const signed char t[16] = {
27 -28, 1, 2, 1,
28 3, 1, 2, 1,
29 4, 1, 2, 1,
30 3, 1, 2, 1
31 };
32
33 bit = 0;
34 if (!(r & 0xffff)) {
35 bit += 16;
36 r >>= 16;
37 }
38 if (!(r & 0xff)) {
39 bit += 8;
40 r >>= 8;
41 }
42 if (!(r & 0xf)) {
43 bit += 4;
44 r >>= 4;
45 }
46
47 return (bit + t[ r & 0xf ]);
48}
diff --git a/src/lib/libc/string/index.c b/src/lib/libc/string/index.c
new file mode 100644
index 0000000000..52d0fd46fa
--- /dev/null
+++ b/src/lib/libc/string/index.c
@@ -0,0 +1,50 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: index.c,v 1.4 2003/06/02 20:18:38 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35
36char *
37#ifdef STRCHR
38strchr(const char *p, int ch)
39#else
40index(const char *p, int ch)
41#endif
42{
43 for (;; ++p) {
44 if (*p == ch)
45 return((char *)p);
46 if (!*p)
47 return((char *)NULL);
48 }
49 /* NOTREACHED */
50}
diff --git a/src/lib/libc/string/memccpy.3 b/src/lib/libc/string/memccpy.3
new file mode 100644
index 0000000000..8c159cb8de
--- /dev/null
+++ b/src/lib/libc/string/memccpy.3
@@ -0,0 +1,73 @@
1.\" $OpenBSD: memccpy.3,v 1.8 2003/06/02 20:18:38 millert 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.\" @(#)memccpy.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd June 9, 1993
33.Dt MEMCCPY 3
34.Os
35.Sh NAME
36.Nm memccpy
37.Nd copy string until character found
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft void *
41.Fn memccpy "void *dst" "const void *src" "int c" "size_t len"
42.Sh DESCRIPTION
43The
44.Fn memccpy
45function copies bytes from string
46.Fa src
47to string
48.Fa dst .
49If the character
50.Fa c
51(as converted to an
52.Li unsigned char )
53occurs in the string
54.Fa src ,
55the copy stops and a pointer to the byte after the copy of
56.Fa c
57in the string
58.Fa dst
59is returned.
60Otherwise,
61.Fa len
62bytes are copied, and a null pointer is returned.
63.Sh SEE ALSO
64.Xr bcopy 3 ,
65.Xr memcpy 3 ,
66.Xr memmove 3 ,
67.Xr strcpy 3 ,
68.Xr strlcpy 3
69.Sh HISTORY
70The
71.Fn memccpy
72function first appeared in
73.Bx 4.4 .
diff --git a/src/lib/libc/string/memccpy.c b/src/lib/libc/string/memccpy.c
new file mode 100644
index 0000000000..265570c5a4
--- /dev/null
+++ b/src/lib/libc/string/memccpy.c
@@ -0,0 +1,56 @@
1/* $OpenBSD: memccpy.c,v 1.5 2005/03/30 20:13:52 otto 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#if defined(LIBC_SCCS) && !defined(lint)
33#if 0
34static char sccsid[] = "@(#)memccpy.c 8.1 (Berkeley) 6/4/93";
35#else
36static char *rcsid = "$OpenBSD: memccpy.c,v 1.5 2005/03/30 20:13:52 otto Exp $";
37#endif
38#endif /* LIBC_SCCS and not lint */
39
40#include <string.h>
41
42void *
43memccpy(void *t, const void *f, int c, size_t n)
44{
45
46 if (n) {
47 unsigned char *tp = t;
48 const unsigned char *fp = f;
49 unsigned char uc = c;
50 do {
51 if ((*tp++ = *fp++) == uc)
52 return (tp);
53 } while (--n != 0);
54 }
55 return (0);
56}
diff --git a/src/lib/libc/string/memchr.3 b/src/lib/libc/string/memchr.3
new file mode 100644
index 0000000000..ddca58bc5e
--- /dev/null
+++ b/src/lib/libc/string/memchr.3
@@ -0,0 +1,74 @@
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: memchr.3,v 1.6 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt MEMCHR 3
36.Os
37.Sh NAME
38.Nm memchr
39.Nd locate byte in byte string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft void *
43.Fn memchr "const void *b" "int c" "size_t len"
44.Sh DESCRIPTION
45The
46.Fn memchr
47function locates the first occurrence of
48.Fa c
49(converted to an
50.Li unsigned char )
51in string
52.Fa b .
53.Sh RETURN VALUES
54The
55.Fn memchr
56function returns a pointer to the byte located, or
57.Dv NULL
58if no such byte exists within
59.Fa len
60bytes.
61.Sh SEE ALSO
62.Xr strchr 3 ,
63.Xr strcspn 3 ,
64.Xr strpbrk 3 ,
65.Xr strrchr 3 ,
66.Xr strsep 3 ,
67.Xr strspn 3 ,
68.Xr strstr 3 ,
69.Xr strtok 3
70.Sh STANDARDS
71The
72.Fn memchr
73function conforms to
74.St -ansiC .
diff --git a/src/lib/libc/string/memchr.c b/src/lib/libc/string/memchr.c
new file mode 100644
index 0000000000..454abcbc17
--- /dev/null
+++ b/src/lib/libc/string/memchr.c
@@ -0,0 +1,51 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: memchr.c,v 1.6 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39void *
40memchr(const void *s, int c, size_t n)
41{
42 if (n != 0) {
43 const unsigned char *p = s;
44
45 do {
46 if (*p++ == (unsigned char)c)
47 return ((void *)(p - 1));
48 } while (--n != 0);
49 }
50 return (NULL);
51}
diff --git a/src/lib/libc/string/memcmp.3 b/src/lib/libc/string/memcmp.3
new file mode 100644
index 0000000000..bd46e6898e
--- /dev/null
+++ b/src/lib/libc/string/memcmp.3
@@ -0,0 +1,77 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: memcmp.3,v 1.5 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt MEMCMP 3
36.Os
37.Sh NAME
38.Nm memcmp
39.Nd compare byte string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft int
43.Fn memcmp "const void *b1" "const void *b2" "size_t len"
44.Sh DESCRIPTION
45The
46.Fn memcmp
47function compares byte string
48.Fa b1
49against byte string
50.Fa b2 .
51Both strings are assumed to be
52.Fa len
53bytes long.
54.Sh RETURN VALUES
55The
56.Fn memcmp
57function returns zero if the two strings are identical,
58otherwise returns the difference between the first two differing bytes
59(treated as
60.Li unsigned char
61values, so that
62.Sq Li \e200
63is greater than
64.Sq Li \&\e0 ,
65for example).
66Zero-length strings are always identical.
67.Sh SEE ALSO
68.Xr bcmp 3 ,
69.Xr strcasecmp 3 ,
70.Xr strcmp 3 ,
71.Xr strcoll 3 ,
72.Xr strxfrm 3
73.Sh STANDARDS
74The
75.Fn memcmp
76function conforms to
77.St -ansiC .
diff --git a/src/lib/libc/string/memcmp.c b/src/lib/libc/string/memcmp.c
new file mode 100644
index 0000000000..6c83208a7b
--- /dev/null
+++ b/src/lib/libc/string/memcmp.c
@@ -0,0 +1,54 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: memcmp.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Compare memory regions.
41 */
42int
43memcmp(const void *s1, const void *s2, size_t n)
44{
45 if (n != 0) {
46 const unsigned char *p1 = s1, *p2 = s2;
47
48 do {
49 if (*p1++ != *p2++)
50 return (*--p1 - *--p2);
51 } while (--n != 0);
52 }
53 return (0);
54}
diff --git a/src/lib/libc/string/memcpy.3 b/src/lib/libc/string/memcpy.3
new file mode 100644
index 0000000000..c8265d94a6
--- /dev/null
+++ b/src/lib/libc/string/memcpy.3
@@ -0,0 +1,77 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: memcpy.3,v 1.6 2003/06/21 12:04:01 avsm Exp $
33.\"
34.Dd June 29, 1991
35.Dt MEMCPY 3
36.Os
37.Sh NAME
38.Nm memcpy
39.Nd copy bytes
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft void *
43.Fn memcpy "void *dst" "const void *src" "size_t len"
44.Sh DESCRIPTION
45The
46.Fn memcpy
47function copies
48.Fa len
49bytes from buffer
50.Fa src
51to buffer
52.Fa dst .
53.Sh RETURN VALUES
54The
55.Fn memcpy
56function returns the original value of
57.Fa dst .
58.Sh SEE ALSO
59.Xr bcopy 3 ,
60.Xr memccpy 3 ,
61.Xr memmove 3 ,
62.Xr strcpy 3 ,
63.Xr strlcpy 3
64.Sh STANDARDS
65The
66.Fn memcpy
67function conforms to
68.St -ansiC .
69.Sh BUGS
70In this implementation
71.Fn memcpy
72is implemented using
73.Xr bcopy 3 ,
74and therefore the buffers may overlap.
75On other systems, copying overlapping buffers may produce surprises.
76A simpler solution is to not use
77.Fn memcpy .
diff --git a/src/lib/libc/string/memmove.3 b/src/lib/libc/string/memmove.3
new file mode 100644
index 0000000000..d4a364eb36
--- /dev/null
+++ b/src/lib/libc/string/memmove.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" 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: memmove.3,v 1.6 2003/06/21 12:04:01 avsm Exp $
33.\"
34.Dd June 29, 1991
35.Dt MEMMOVE 3
36.Os
37.Sh NAME
38.Nm memmove
39.Nd copy bytes
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft void *
43.Fn memmove "void *dst" "const void *src" "size_t len"
44.Sh DESCRIPTION
45The
46.Fn memmove
47function copies
48.Fa len
49bytes from buffer
50.Fa src
51to buffer
52.Fa dst .
53The two buffers may overlap;
54the copy is always done in a non-destructive manner.
55.Sh RETURN VALUES
56The
57.Fn memmove
58function returns the original value of
59.Fa dst .
60.Sh SEE ALSO
61.Xr bcopy 3 ,
62.Xr memccpy 3 ,
63.Xr memcpy 3 ,
64.Xr strcpy 3 ,
65.Xr strlcpy 3
66.Sh STANDARDS
67The
68.Fn memmove
69function conforms to
70.St -ansiC .
diff --git a/src/lib/libc/string/memset.3 b/src/lib/libc/string/memset.3
new file mode 100644
index 0000000000..291b1427dc
--- /dev/null
+++ b/src/lib/libc/string/memset.3
@@ -0,0 +1,67 @@
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: memset.3,v 1.5 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt MEMSET 3
36.Os
37.Sh NAME
38.Nm memset
39.Nd write a byte to byte string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft void *
43.Fn memset "void *b" "int c" "size_t len"
44.Sh DESCRIPTION
45The
46.Fn memset
47function writes
48.Fa len
49bytes of value
50.Fa c
51(converted to an
52.Li unsigned char )
53to the string
54.Fa b .
55.Sh RETURN VALUES
56The
57.Fn memset
58function returns the original value of
59.Fa b .
60.Sh SEE ALSO
61.Xr bzero 3 ,
62.Xr swab 3
63.Sh STANDARDS
64The
65.Fn memset
66function conforms to
67.St -ansiC .
diff --git a/src/lib/libc/string/memset.c b/src/lib/libc/string/memset.c
new file mode 100644
index 0000000000..9bc0556faa
--- /dev/null
+++ b/src/lib/libc/string/memset.c
@@ -0,0 +1,51 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: memset.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39void *
40memset(void *dst, int c, size_t n)
41{
42
43 if (n != 0) {
44 char *d = dst;
45
46 do
47 *d++ = c;
48 while (--n != 0);
49 }
50 return (dst);
51}
diff --git a/src/lib/libc/string/rindex.c b/src/lib/libc/string/rindex.c
new file mode 100644
index 0000000000..b880d0eaeb
--- /dev/null
+++ b/src/lib/libc/string/rindex.c
@@ -0,0 +1,52 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: rindex.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35
36char *
37#ifdef STRRCHR
38strrchr(const char *p, int ch)
39#else
40rindex(const char *p, int ch)
41#endif
42{
43 char *save;
44
45 for (save = NULL;; ++p) {
46 if (*p == ch)
47 save = (char *)p;
48 if (!*p)
49 return(save);
50 }
51 /* NOTREACHED */
52}
diff --git a/src/lib/libc/string/strcasecmp.3 b/src/lib/libc/string/strcasecmp.3
new file mode 100644
index 0000000000..c4253e5afd
--- /dev/null
+++ b/src/lib/libc/string/strcasecmp.3
@@ -0,0 +1,84 @@
1.\" $OpenBSD: strcasecmp.3,v 1.9 2005/02/25 03:12:44 cloder Exp $
2.\"
3.\" Copyright (c) 1990, 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.\" Chris Torek.
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.\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93
33.\"
34.Dd June 9, 1993
35.Dt STRCASECMP 3
36.Os
37.Sh NAME
38.Nm strcasecmp ,
39.Nm strncasecmp
40.Nd compare strings, ignoring case
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft int
44.Fn strcasecmp "const char *s1" "const char *s2"
45.Ft int
46.Fn strncasecmp "const char *s1" "const char *s2" "size_t len"
47.Sh DESCRIPTION
48The
49.Fn strcasecmp
50and
51.Fn strncasecmp
52functions compare the NUL-terminated strings
53.Fa s1
54and
55.Fa s2
56and return an integer greater than, equal to, or less than 0,
57according to whether
58.Fa s1
59is lexicographically greater than, equal to, or less than
60.Fa s2
61after translation of each corresponding character to lower-case.
62The strings themselves are not modified.
63The comparison is done using unsigned characters, so that
64.Sq Li \e200
65is greater than
66.Ql \e0 .
67.Pp
68.Fn strncasecmp
69compares at most
70.Fa len
71characters.
72.Sh SEE ALSO
73.Xr bcmp 3 ,
74.Xr memcmp 3 ,
75.Xr strcmp 3 ,
76.Xr strcoll 3 ,
77.Xr strxfrm 3
78.Sh HISTORY
79The
80.Fn strcasecmp
81and
82.Fn strncasecmp
83functions first appeared in
84.Bx 4.4 .
diff --git a/src/lib/libc/string/strcasecmp.c b/src/lib/libc/string/strcasecmp.c
new file mode 100644
index 0000000000..62da063444
--- /dev/null
+++ b/src/lib/libc/string/strcasecmp.c
@@ -0,0 +1,113 @@
1/* $OpenBSD: strcasecmp.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1987, 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 <string.h>
33
34#if defined(LIBC_SCCS) && !defined(lint)
35#if 0
36static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
37#else
38static char *rcsid = "$OpenBSD: strcasecmp.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
39#endif
40#endif /* LIBC_SCCS and not lint */
41
42typedef unsigned char u_char;
43
44/*
45 * This array is designed for mapping upper and lower case letter
46 * together for a case independent comparison. The mappings are
47 * based upon ascii character sequences.
48 */
49static const u_char charmap[] = {
50 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
51 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
52 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
53 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
54 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
55 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
56 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
57 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
58 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
59 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
60 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
61 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
62 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
63 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
64 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
65 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
66 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
67 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
68 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
69 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
70 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
71 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
72 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
73 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
74 '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
75 '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
76 '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
77 '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
78 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
79 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
80 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
81 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
82};
83
84int
85strcasecmp(const char *s1, const char *s2)
86{
87 const u_char *cm = charmap;
88 const u_char *us1 = (const u_char *)s1;
89 const u_char *us2 = (const u_char *)s2;
90
91 while (cm[*us1] == cm[*us2++])
92 if (*us1++ == '\0')
93 return (0);
94 return (cm[*us1] - cm[*--us2]);
95}
96
97int
98strncasecmp(const char *s1, const char *s2, size_t n)
99{
100 if (n != 0) {
101 const u_char *cm = charmap;
102 const u_char *us1 = (const u_char *)s1;
103 const u_char *us2 = (const u_char *)s2;
104
105 do {
106 if (cm[*us1] != cm[*us2++])
107 return (cm[*us1] - cm[*--us2]);
108 if (*us1++ == '\0')
109 break;
110 } while (--n != 0);
111 }
112 return (0);
113}
diff --git a/src/lib/libc/string/strcasestr.c b/src/lib/libc/string/strcasestr.c
new file mode 100644
index 0000000000..075e6f1987
--- /dev/null
+++ b/src/lib/libc/string/strcasestr.c
@@ -0,0 +1,64 @@
1/* $OpenBSD: strcasestr.c,v 1.1 2005/03/30 03:04:19 deraadt Exp $ */
2/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
3
4/*-
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: strcasestr.c,v 1.1 2005/03/30 03:04:19 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <ctype.h>
41#include <string.h>
42
43/*
44 * Find the first occurrence of find in s, ignore case.
45 */
46char *
47strcasestr(const char *s, const char *find)
48{
49 char c, sc;
50 size_t len;
51
52 if ((c = *find++) != 0) {
53 c = tolower((unsigned char)c);
54 len = strlen(find);
55 do {
56 do {
57 if ((sc = *s++) == 0)
58 return (NULL);
59 } while ((char)tolower((unsigned char)sc) != c);
60 } while (strncasecmp(s, find, len) != 0);
61 s--;
62 }
63 return ((char *)s);
64}
diff --git a/src/lib/libc/string/strcat.3 b/src/lib/libc/string/strcat.3
new file mode 100644
index 0000000000..89d368c3fb
--- /dev/null
+++ b/src/lib/libc/string/strcat.3
@@ -0,0 +1,131 @@
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: strcat.3,v 1.10 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd July 8, 1997
35.Dt STRCAT 3
36.Os
37.Sh NAME
38.Nm strcat ,
39.Nm strncat
40.Nd concatenate strings
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strcat "char *s" "const char *append"
45.Ft char *
46.Fn strncat "char *s" "const char *append" "size_t count"
47.Sh DESCRIPTION
48The
49.Fn strcat
50and
51.Fn strncat
52functions append a copy of the NUL-terminated string
53.Fa append
54to the end of the NUL-terminated string
55.Fa s ,
56then add a terminating
57.Ql \e0 .
58The string
59.Fa s
60must have sufficient space to hold the result.
61.Pp
62The
63.Fn strncat
64function appends not more than
65.Fa count
66characters where space for the terminating
67.Ql \e0
68should not be included in
69.Fa count .
70.Sh RETURN VALUES
71The
72.Fn strcat
73and
74.Fn strncat
75functions return the pointer
76.Fa s .
77.Sh EXAMPLES
78The following appends
79.Dq Li abc
80to
81.Dq Li chararray :
82.Bd -literal -offset indent
83char *letters = "abcdefghi";
84
85(void)strncat(chararray, letters, 3);
86.Ed
87.Pp
88The following example shows how to use
89.Fn strncat
90safely in conjunction with
91.Xr strncpy 3 .
92.Bd -literal -offset indent
93char buf[BUFSIZ];
94char *input, *suffix;
95
96(void)strncpy(buf, input, sizeof(buf) - 1);
97buf[sizeof(buf) - 1] = '\e0';
98(void)strncat(buf, suffix, sizeof(buf) - 1 - strlen(buf));
99.Ed
100.Pp
101The above will copy as many characters from
102.Dq Li input
103to
104.Dq Li buf
105as will fit.
106It then appends as many characters from suffix as will fit (or none
107if there is no space).
108For operations like this, the
109.Xr strlcpy 3
110and
111.Xr strlcat 3
112functions are a better choice, as shown below.
113.Bd -literal -offset indent
114(void)strlcpy(buf, input, sizeof(buf));
115(void)strlcat(buf, suffix, sizeof(buf));
116.Ed
117.Sh SEE ALSO
118.Xr bcopy 3 ,
119.Xr memccpy 3 ,
120.Xr memcpy 3 ,
121.Xr memmove 3 ,
122.Xr strcpy 3 ,
123.Xr strlcat 3 ,
124.Xr strlcpy 3
125.Sh STANDARDS
126The
127.Fn strcat
128and
129.Fn strncat
130functions conform to
131.St -ansiC .
diff --git a/src/lib/libc/string/strcat.c b/src/lib/libc/string/strcat.c
new file mode 100644
index 0000000000..4f9734ab9e
--- /dev/null
+++ b/src/lib/libc/string/strcat.c
@@ -0,0 +1,55 @@
1/* $OpenBSD: strcat.c,v 1.7 2004/11/28 07:16:54 mickey Exp $ */
2
3/*
4 * Copyright (c) 1988 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: strcat.c,v 1.7 2004/11/28 07:16:54 mickey Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42#if defined(APIWARN)
43__warn_references(strcat,
44 "warning: strcat() is almost always misused, please use strlcat()");
45#endif
46
47char *
48strcat(char *s, const char *append)
49{
50 char *save = s;
51
52 for (; *s; ++s);
53 while ((*s++ = *append++) != '\0');
54 return(save);
55}
diff --git a/src/lib/libc/string/strchr.3 b/src/lib/libc/string/strchr.3
new file mode 100644
index 0000000000..86841bac25
--- /dev/null
+++ b/src/lib/libc/string/strchr.3
@@ -0,0 +1,102 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" 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: strchr.3,v 1.8 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRCHR 3
36.Os
37.Sh NAME
38.Nm strchr ,
39.Nm index
40.Nd locate first occurrence of a character in a string
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strchr "const char *s" "int c"
45.Ft char *
46.Fn index "const char *s" "int c"
47.Sh DESCRIPTION
48The
49.Fn strchr
50function locates the first occurrence of the character
51.Fa c
52in the string
53.Fa s .
54The terminating NUL character is considered part of the string.
55If
56.Fa c
57is
58.Ql \e0 ,
59.Fn strchr
60locates the terminating
61.Ql \e0 .
62.Pp
63The
64.Fn index
65function is an old synonym for
66.Fn strchr .
67.Sh RETURN VALUES
68The
69.Fn strchr
70function returns a pointer to the located character or
71.Dv NULL
72if the character does not appear in the string.
73.Sh EXAMPLES
74After the following call to
75.Fn strchr ,
76.Va p
77will point to the string
78.Qq oobar :
79.Bd -literal -offset indent
80char *p;
81char *s = "foobar";
82
83p = strchr(s, 'o');
84.Ed
85.Sh SEE ALSO
86.Xr memchr 3 ,
87.Xr strcspn 3 ,
88.Xr strpbrk 3 ,
89.Xr strrchr 3 ,
90.Xr strsep 3 ,
91.Xr strspn 3 ,
92.Xr strstr 3 ,
93.Xr strtok 3
94.Sh STANDARDS
95The
96.Fn strchr
97function conforms to
98.St -ansiC .
99.Pp
100The
101.Fn index
102function is deprecated and shouldn't be used in new code.
diff --git a/src/lib/libc/string/strcmp.3 b/src/lib/libc/string/strcmp.3
new file mode 100644
index 0000000000..953181e8de
--- /dev/null
+++ b/src/lib/libc/string/strcmp.3
@@ -0,0 +1,87 @@
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: strcmp.3,v 1.8 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRCMP 3
36.Os
37.Sh NAME
38.Nm strcmp ,
39.Nm strncmp
40.Nd compare strings
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft int
44.Fn strcmp "const char *s1" "const char *s2"
45.Ft int
46.Fn strncmp "const char *s1" "const char *s2" "size_t len"
47.Sh DESCRIPTION
48The
49.Fn strcmp
50and
51.Fn strncmp
52functions lexicographically compare the NUL-terminated strings
53.Fa s1
54and
55.Fa s2 .
56.Sh RETURN VALUES
57The
58.Fn strcmp
59and
60.Fn strncmp
61return an integer greater than, equal to, or less than 0, according
62to whether the string
63.Fa s1
64is greater than, equal to, or less than the string
65.Fa s2 .
66The comparison is done using unsigned characters, so that
67.Ql \e200
68is greater than
69.Ql \e0 .
70.Pp
71.Fn strncmp
72compares at most
73.Fa len
74characters.
75.Sh SEE ALSO
76.Xr bcmp 3 ,
77.Xr memcmp 3 ,
78.Xr strcasecmp 3 ,
79.Xr strcoll 3 ,
80.Xr strxfrm 3
81.Sh STANDARDS
82The
83.Fn strcmp
84and
85.Fn strncmp
86functions conform to
87.St -ansiC .
diff --git a/src/lib/libc/string/strcmp.c b/src/lib/libc/string/strcmp.c
new file mode 100644
index 0000000000..0fe34c2804
--- /dev/null
+++ b/src/lib/libc/string/strcmp.c
@@ -0,0 +1,55 @@
1/* $OpenBSD: strcmp.c,v 1.6 2004/11/28 07:16:54 mickey Exp $ */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
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#if defined(LIBC_SCCS) && !defined(lint)
36static char *rcsid = "$OpenBSD: strcmp.c,v 1.6 2004/11/28 07:16:54 mickey Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#if !defined(_KERNEL) && !defined(_STANDALONE)
40#include <string.h>
41#else
42#include <lib/libkern/libkern.h>
43#endif
44
45/*
46 * Compare strings.
47 */
48int
49strcmp(const char *s1, const char *s2)
50{
51 while (*s1 == *s2++)
52 if (*s1++ == 0)
53 return (0);
54 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
55}
diff --git a/src/lib/libc/string/strcoll.3 b/src/lib/libc/string/strcoll.3
new file mode 100644
index 0000000000..d1a4e60dc6
--- /dev/null
+++ b/src/lib/libc/string/strcoll.3
@@ -0,0 +1,68 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" 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: strcoll.3,v 1.6 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRCOLL 3
36.Os
37.Sh NAME
38.Nm strcoll
39.Nd compare strings according to current collation
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft int
43.Fn strcoll "const char *s1" "const char *s2"
44.Sh DESCRIPTION
45The
46.Fn strcoll
47function lexicographically compares the NUL-terminated strings
48.Fa s1
49and
50.Fa s2
51according to the current locale collation
52and returns an integer greater than, equal to, or less than 0,
53according to whether
54.Fa s1
55is greater than, equal to, or less than
56.Fa s2 .
57.Sh SEE ALSO
58.Xr bcmp 3 ,
59.Xr memcmp 3 ,
60.Xr setlocale 3 ,
61.Xr strcasecmp 3 ,
62.Xr strcmp 3 ,
63.Xr strxfrm 3
64.Sh STANDARDS
65The
66.Fn strcoll
67function conforms to
68.St -ansiC .
diff --git a/src/lib/libc/string/strcoll.c b/src/lib/libc/string/strcoll.c
new file mode 100644
index 0000000000..9622b67281
--- /dev/null
+++ b/src/lib/libc/string/strcoll.c
@@ -0,0 +1,47 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: strcoll.c,v 1.4 2003/06/11 21:08:29 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Compare strings according to LC_COLLATE category of current locale.
41 */
42int
43strcoll(const char *s1, const char *s2)
44{
45 /* LC_COLLATE is unimplemented, hence always "C" */
46 return (strcmp(s1, s2));
47}
diff --git a/src/lib/libc/string/strcpy.3 b/src/lib/libc/string/strcpy.3
new file mode 100644
index 0000000000..504f42f2ba
--- /dev/null
+++ b/src/lib/libc/string/strcpy.3
@@ -0,0 +1,150 @@
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: strcpy.3,v 1.13 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRCPY 3
36.Os
37.Sh NAME
38.Nm strcpy ,
39.Nm strncpy
40.Nd copy strings
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strcpy "char *dst" "const char *src"
45.Ft char *
46.Fn strncpy "char *dst" "const char *src" "size_t len"
47.Sh DESCRIPTION
48The
49.Fn strcpy
50and
51.Fn strncpy
52functions copy the string
53.Fa src
54to
55.Fa dst
56(including the terminating
57.Ql \e0
58character).
59.Pp
60.Fn strncpy
61copies not more than
62.Fa len
63characters into
64.Fa dst ,
65appending
66.Ql \e0
67characters if
68.Fa src
69is less than
70.Fa len
71characters long, and
72.Em not
73terminating
74.Fa dst
75if the length of
76.Fa src
77is greater than or equal to
78.Fa len .
79.Sh RETURN VALUES
80The
81.Fn strcpy
82and
83.Fn strncpy
84functions return
85.Fa dst .
86.Sh EXAMPLES
87The following sets
88.Va chararray
89to
90.Dq abc\e0\e0\e0 :
91.Bd -literal -offset indent
92(void)strncpy(chararray, "abc", 6);
93.Ed
94.Pp
95The following sets
96.Va chararray
97to
98.Dq abcdef
99and does
100.Em not
101NUL terminate
102.Va chararray
103because the source string is >= the length parameter.
104.Fn strncpy
105.Em only
106NUL terminates the destination string when the length of the source
107string is less than the length parameter.
108.Bd -literal -offset indent
109(void)strncpy(chararray, "abcdefgh", 6);
110.Ed
111.Pp
112The following copies as many characters from
113.Va input
114to
115.Va buf
116as will fit and NUL terminates the result.
117Because
118.Fn strncpy
119does
120.Em not
121guarantee to NUL terminate the string itself, we must do this by hand.
122.Bd -literal -offset indent
123char buf[BUFSIZ];
124
125(void)strncpy(buf, input, sizeof(buf) - 1);
126buf[sizeof(buf) - 1] = '\e0';
127.Ed
128.Pp
129Note that
130.Xr strlcpy 3
131is a better choice for this kind of operation.
132The equivalent using
133.Xr strlcpy 3
134is simply:
135.Bd -literal -offset indent
136(void)strlcpy(buf, input, sizeof(buf));
137.Ed
138.Sh SEE ALSO
139.Xr bcopy 3 ,
140.Xr memccpy 3 ,
141.Xr memcpy 3 ,
142.Xr memmove 3 ,
143.Xr strlcpy 3
144.Sh STANDARDS
145The
146.Fn strcpy
147and
148.Fn strncpy
149functions conform to
150.St -ansiC .
diff --git a/src/lib/libc/string/strcpy.c b/src/lib/libc/string/strcpy.c
new file mode 100644
index 0000000000..0acd1bbadf
--- /dev/null
+++ b/src/lib/libc/string/strcpy.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: strcpy.c,v 1.7 2004/11/28 07:16:54 mickey Exp $ */
2
3/*
4 * Copyright (c) 1988 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: strcpy.c,v 1.7 2004/11/28 07:16:54 mickey Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42#if defined(APIWARN)
43__warn_references(strcpy,
44 "warning: strcpy() is almost always misused, please use strlcpy()");
45#endif
46
47char *
48strcpy(char *to, const char *from)
49{
50 char *save = to;
51
52 for (; (*to = *from) != '\0'; ++from, ++to);
53 return(save);
54}
diff --git a/src/lib/libc/string/strcspn.3 b/src/lib/libc/string/strcspn.3
new file mode 100644
index 0000000000..c28d99a901
--- /dev/null
+++ b/src/lib/libc/string/strcspn.3
@@ -0,0 +1,88 @@
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: strcspn.3,v 1.7 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRCSPN 3
36.Os
37.Sh NAME
38.Nm strcspn
39.Nd span the complement of a string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft size_t
43.Fn strcspn "const char *s" "const char *charset"
44.Sh DESCRIPTION
45The
46.Fn strcspn
47function spans the initial part of the NUL-terminated string
48.Fa s
49as long as the characters from
50.Fa s
51do not occur in string
52.Fa charset
53(it spans the
54.Em complement
55of
56.Fa charset ) .
57.Sh RETURN VALUES
58The
59.Fn strcspn
60function returns the number of characters spanned.
61.Sh EXAMPLES
62The following call to
63.Fn strcspn
64will return 3, since the first three characters of string
65.Fa s
66do not occur in string
67.Fa charset :
68.Bd -literal -offset indent
69char *s = "foobar";
70char *charset = "bar";
71size_t span;
72
73span = strcspn(s, charset);
74.Ed
75.Sh SEE ALSO
76.Xr memchr 3 ,
77.Xr strchr 3 ,
78.Xr strpbrk 3 ,
79.Xr strrchr 3 ,
80.Xr strsep 3 ,
81.Xr strspn 3 ,
82.Xr strstr 3 ,
83.Xr strtok 3
84.Sh STANDARDS
85The
86.Fn strcspn
87function conforms to
88.St -ansiC .
diff --git a/src/lib/libc/string/strcspn.c b/src/lib/libc/string/strcspn.c
new file mode 100644
index 0000000000..f96f903809
--- /dev/null
+++ b/src/lib/libc/string/strcspn.c
@@ -0,0 +1,61 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: strcspn.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Span the complement of string s2.
41 */
42size_t
43strcspn(const char *s1, const char *s2)
44{
45 const char *p, *spanp;
46 char c, sc;
47
48 /*
49 * Stop as soon as we find any character from s2. Note that there
50 * must be a NUL in s2; it suffices to stop when we find that, too.
51 */
52 for (p = s1;;) {
53 c = *p++;
54 spanp = s2;
55 do {
56 if ((sc = *spanp++) == c)
57 return (p - 1 - s1);
58 } while (sc != 0);
59 }
60 /* NOTREACHED */
61}
diff --git a/src/lib/libc/string/strdup.3 b/src/lib/libc/string/strdup.3
new file mode 100644
index 0000000000..a434312c42
--- /dev/null
+++ b/src/lib/libc/string/strdup.3
@@ -0,0 +1,84 @@
1.\" $OpenBSD: strdup.3,v 1.13 2005/02/25 03:12:44 cloder 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.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd June 9, 1993
33.Dt STRDUP 3
34.Os
35.Sh NAME
36.Nm strdup
37.Nd save a copy of a string
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft char *
41.Fn strdup "const char *s"
42.Sh DESCRIPTION
43The
44.Fn strdup
45function allocates sufficient memory for a copy of the string
46.Fa s ,
47does the copy, and returns a pointer to it.
48The pointer may subsequently be used as an argument to the function
49.Xr free 3 .
50.Pp
51If insufficient memory is available,
52.Dv NULL
53is returned.
54.Sh EXAMPLES
55The following will point
56.Va p
57to an allocated area of memory containing the NUL-terminated string
58.Qq foobar :
59.Bd -literal -offset indent
60char *p;
61
62if ((p = strdup("foobar")) == NULL) {
63 fprintf(stderr, "Out of memory.\en");
64 exit(1);
65}
66.Ed
67.Sh ERRORS
68The
69.Fn strdup
70function may fail and set the external variable
71.Va errno
72for any of the errors specified for the library function
73.Xr malloc 3 .
74.Sh SEE ALSO
75.Xr free 3 ,
76.Xr malloc 3 ,
77.Xr strcpy 3 ,
78.Xr strlcpy 3 ,
79.Xr strlen 3
80.Sh HISTORY
81The
82.Fn strdup
83function first appeared in
84.Bx 4.4 .
diff --git a/src/lib/libc/string/strdup.c b/src/lib/libc/string/strdup.c
new file mode 100644
index 0000000000..bbea59888c
--- /dev/null
+++ b/src/lib/libc/string/strdup.c
@@ -0,0 +1,57 @@
1/* $OpenBSD: strdup.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1988, 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#if defined(LIBC_SCCS) && !defined(lint)
33#if 0
34static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
35#else
36static char *rcsid = "$OpenBSD: strdup.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
37#endif
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/types.h>
41
42#include <stddef.h>
43#include <stdlib.h>
44#include <string.h>
45
46char *
47strdup(const char *str)
48{
49 size_t siz;
50 char *copy;
51
52 siz = strlen(str) + 1;
53 if ((copy = malloc(siz)) == NULL)
54 return(NULL);
55 (void)memcpy(copy, str, siz);
56 return(copy);
57}
diff --git a/src/lib/libc/string/strerror.3 b/src/lib/libc/string/strerror.3
new file mode 100644
index 0000000000..066cc0e28b
--- /dev/null
+++ b/src/lib/libc/string/strerror.3
@@ -0,0 +1,113 @@
1.\" Copyright (c) 1980, 1991 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: strerror.3,v 1.8 2004/12/10 03:54:18 jaredy Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRERROR 3
36.Os
37.Sh NAME
38.Nm strerror
39.Nd get error message string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft char *
43.Fn strerror "int errnum"
44.Ft int
45.Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
46.Sh DESCRIPTION
47The
48.Fn strerror
49and
50.Fn strerror_r
51functions map the error number
52.Fa errnum
53to a language-dependent error message string.
54.Pp
55.Fn strerror
56returns a string containing a maximum of
57.Dv NL_TEXTMAX
58characters, including the trailing NUL.
59This string is not to be modified by the calling program,
60but may be overwritten by subsequent calls to
61.Fn strerror .
62.Pp
63.Fn strerror_r
64is a thread safe version of
65.Fn strerror
66that places the error message in the specified buffer
67.Fa strerrbuf .
68.Sh RETURN VALUES
69.Fn strerror
70returns a pointer to the error message string.
71If an error occurs, the error code is stored in
72.Va errno .
73.Pp
74.Fn strerror_r
75returns zero upon successful completion.
76If an error occurs, the error code is stored in
77.Va errno
78and the error code is returned.
79.Sh ERRORS
80.Fn strerror
81and
82.Fn strerror_r
83may fail if:
84.Bl -tag -width Er
85.It Bq Er EINVAL
86.Fa errnum
87is not a valid error number.
88The returned error string will consist of an error message that includes
89.Fa errnum .
90.El
91.Pp
92.Fn strerror_r
93may fail if:
94.Bl -tag -width Er
95.It Bq Er ERANGE
96The error message is larger than
97.Fa buflen
98characters.
99The message will be truncated to fit.
100.El
101.Sh SEE ALSO
102.Xr intro 2 ,
103.Xr perror 3 ,
104.Xr setlocale 3
105.Sh STANDARDS
106The
107.Fn strerror
108function conforms to
109.St -ansiC .
110The
111.Fn strerror_r
112function conforms to
113.St -p1003.1 .
diff --git a/src/lib/libc/string/strerror.c b/src/lib/libc/string/strerror.c
new file mode 100644
index 0000000000..edb6af7386
--- /dev/null
+++ b/src/lib/libc/string/strerror.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strerror.c,v 1.6 2004/05/03 05:07:34 espie Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35#include <limits.h>
36
37char *
38strerror(int num)
39{
40 static char buf[NL_TEXTMAX];
41
42 (void)strerror_r(num, buf, sizeof(buf));
43 return (buf);
44}
diff --git a/src/lib/libc/string/strerror_r.c b/src/lib/libc/string/strerror_r.c
new file mode 100644
index 0000000000..c0ca434cbd
--- /dev/null
+++ b/src/lib/libc/string/strerror_r.c
@@ -0,0 +1,124 @@
1/* $OpenBSD: strerror_r.c,v 1.3 2005/04/20 23:38:15 beck Exp $ */
2/* Public Domain <marc@snafu.org> */
3
4#if defined(LIBC_SCCS) && !defined(lint)
5static char *rcsid = "$OpenBSD: strerror_r.c,v 1.3 2005/04/20 23:38:15 beck Exp $";
6#endif /* LIBC_SCCS and not lint */
7
8#ifdef NLS
9#define catclose _catclose
10#define catgets _catgets
11#define catopen _catopen
12#include <nl_types.h>
13#endif
14
15#define sys_errlist _sys_errlist
16#define sys_nerr _sys_nerr
17
18#include <errno.h>
19#include <limits.h>
20#include <string.h>
21
22static size_t
23__digits10(unsigned int num)
24{
25 size_t i = 0;
26
27 do {
28 num /= 10;
29 i++;
30 } while (num != 0);
31
32 return i;
33}
34
35static void
36__itoa(int num, char *buffer, size_t start, size_t end)
37{
38 size_t pos;
39 unsigned int a;
40 int neg;
41
42 if (num < 0) {
43 a = -num;
44 neg = 1;
45 }
46 else {
47 a = num;
48 neg = 0;
49 }
50
51 pos = start + __digits10(a);
52 if (neg)
53 pos++;
54
55 if (pos < end)
56 buffer[pos] = '\0';
57 else {
58 if (end)
59 buffer[--end] = '\0'; /* XXX */
60 }
61 pos--;
62 do {
63
64 if (pos < end)
65 buffer[pos] = (a % 10) + '0';
66 pos--;
67 a /= 10;
68 } while (a != 0);
69 if (neg)
70 if (pos < end)
71 buffer[pos] = '-';
72}
73
74
75#define UPREFIX "Unknown error: "
76
77int
78strerror_r(int errnum, char *strerrbuf, size_t buflen)
79{
80 int save_errno;
81 int ret_errno;
82 size_t len;
83#ifdef NLS
84 nl_catd catd;
85#endif
86
87 save_errno = errno;
88 ret_errno = 0;
89
90#ifdef NLS
91 catd = catopen("libc", 0);
92#endif
93
94 if (errnum >= 0 && errnum < sys_nerr) {
95#ifdef NLS
96 len = strlcpy(strerrbuf, catgets(catd, 1, errnum,
97 (char *)sys_errlist[errnum]), buflen);
98#else
99 len = strlcpy(strerrbuf, sys_errlist[errnum], buflen);
100#endif
101 if (len >= buflen)
102 ret_errno = ERANGE;
103 } else {
104#ifdef NLS
105 len = strlcpy(strerrbuf, catgets(catd, 1, 0xffff, UPREFIX),
106 buflen);
107#else
108 len = strlcpy(strerrbuf, UPREFIX, buflen);
109#endif
110 if (len >= buflen)
111 ret_errno = ERANGE;
112 else {
113 __itoa(errnum, strerrbuf, len, buflen);
114 ret_errno = EINVAL;
115 }
116 }
117
118#ifdef NLS
119 catclose(catd);
120#endif
121
122 errno = ret_errno ? ret_errno : save_errno;
123 return (ret_errno);
124}
diff --git a/src/lib/libc/string/string.3 b/src/lib/libc/string/string.3
new file mode 100644
index 0000000000..690cf4dbda
--- /dev/null
+++ b/src/lib/libc/string/string.3
@@ -0,0 +1,136 @@
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: string.3,v 1.11 2005/02/25 03:12:44 cloder Exp $
31.\"
32.Dd April 19, 1991
33.Dt STRING 3
34.Os
35.Sh NAME
36.Nm string
37.Nd string specific functions
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft char *
41.Fn strcat "char *s" "const char *append"
42.Ft char *
43.Fn strlcat "char *s" "const char *append" "size_t size"
44.Ft char *
45.Fn strncat "char *s" "const char *append" "size_t count"
46.Ft char *
47.Fn strchr "const char *s" "int c"
48.Ft char *
49.Fn strrchr "const char *s" "int c"
50.Ft int
51.Fn strcmp "const char *s1" "const char *s2"
52.Ft int
53.Fn strncmp "const char *s1" "const char *s2" "size_t count"
54.Ft int
55.Fn strcasecmp "const char *s1" "const char *s2"
56.Ft int
57.Fn strncasecmp "const char *s1" "const char *s2" "size_t count"
58.Ft char *
59.Fn strcpy "char *dst" "const char *src"
60.Ft char *
61.Fn strlcpy "char *dst" "const char *src" "size_t size"
62.Ft char *
63.Fn strncpy "char *dst" "const char *src" "size_t count"
64.Ft char *
65.Fn strerror "int errno"
66.Ft size_t
67.Fn strlen "const char *s"
68.Ft char *
69.Fn strpbrk "const char *s" "const char *charset"
70.Ft char *
71.Fn strsep "char **stringp" "const char *delim"
72.Ft size_t
73.Fn strspn "const char *s" "const char *charset"
74.Ft size_t
75.Fn strcspn "const char *s" "const char *charset"
76.Ft char *
77.Fn strstr "const char *big" "const char *little"
78.Ft char *
79.Fn strtok "char *s" "const char *delim"
80.Ft char *
81.Fn index "const char *s" "int c"
82.Ft char *
83.Fn rindex "const char *s" "int c"
84.Sh DESCRIPTION
85The string functions
86manipulate strings terminated by a
87NUL byte.
88.Pp
89See the specific manual pages for more information.
90For manipulating variable length generic objects as byte
91strings (without the NUL-byte check), see
92.Xr bstring 3 .
93.Pp
94Except as noted in their specific manual pages,
95the string functions do not test the destination
96for size limitations.
97.Sh SEE ALSO
98.Xr bstring 3 ,
99.Xr index 3 ,
100.Xr rindex 3 ,
101.Xr strcasecmp 3 ,
102.Xr strcat 3 ,
103.Xr strchr 3 ,
104.Xr strcmp 3 ,
105.Xr strcpy 3 ,
106.Xr strcspn 3 ,
107.Xr strerror 3 ,
108.Xr strlcat 3 ,
109.Xr strlcpy 3 ,
110.Xr strlen 3 ,
111.Xr strpbrk 3 ,
112.Xr strrchr 3 ,
113.Xr strsep 3 ,
114.Xr strspn 3 ,
115.Xr strstr 3 ,
116.Xr strtok 3
117.Sh STANDARDS
118The
119.Fn strcat ,
120.Fn strncat ,
121.Fn strchr ,
122.Fn strrchr ,
123.Fn strcmp ,
124.Fn strncmp ,
125.Fn strcpy ,
126.Fn strncpy ,
127.Fn strerror ,
128.Fn strlen ,
129.Fn strpbrk ,
130.Fn strspn ,
131.Fn strcspn ,
132.Fn strstr ,
133and
134.Fn strtok
135functions conform to
136.St -ansiC .
diff --git a/src/lib/libc/string/strlcat.c b/src/lib/libc/string/strlcat.c
new file mode 100644
index 0000000000..952eed1a79
--- /dev/null
+++ b/src/lib/libc/string/strlcat.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: strlcat.c,v 1.12 2005/03/30 20:13:52 otto Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20static char *rcsid = "$OpenBSD: strlcat.c,v 1.12 2005/03/30 20:13:52 otto Exp $";
21#endif /* LIBC_SCCS and not lint */
22
23#include <sys/types.h>
24#include <string.h>
25
26/*
27 * Appends src to string dst of size siz (unlike strncat, siz is the
28 * full size of dst, not space left). At most siz-1 characters
29 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
30 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
31 * If retval >= siz, truncation occurred.
32 */
33size_t
34strlcat(char *dst, const char *src, size_t siz)
35{
36 char *d = dst;
37 const char *s = src;
38 size_t n = siz;
39 size_t dlen;
40
41 /* Find the end of dst and adjust bytes left but don't go past end */
42 while (n-- != 0 && *d != '\0')
43 d++;
44 dlen = d - dst;
45 n = siz - dlen;
46
47 if (n == 0)
48 return(dlen + strlen(s));
49 while (*s != '\0') {
50 if (n != 1) {
51 *d++ = *s;
52 n--;
53 }
54 s++;
55 }
56 *d = '\0';
57
58 return(dlen + (s - src)); /* count does not include NUL */
59}
diff --git a/src/lib/libc/string/strlcpy.3 b/src/lib/libc/string/strlcpy.3
new file mode 100644
index 0000000000..b392588879
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.3
@@ -0,0 +1,179 @@
1.\" $OpenBSD: strlcpy.3,v 1.16 2003/06/17 21:56:24 millert Exp $
2.\"
3.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd June 22, 1998
18.Dt STRLCPY 3
19.Os
20.Sh NAME
21.Nm strlcpy ,
22.Nm strlcat
23.Nd size-bounded string copying and concatenation
24.Sh SYNOPSIS
25.Fd #include <string.h>
26.Ft size_t
27.Fn strlcpy "char *dst" "const char *src" "size_t size"
28.Ft size_t
29.Fn strlcat "char *dst" "const char *src" "size_t size"
30.Sh DESCRIPTION
31The
32.Fn strlcpy
33and
34.Fn strlcat
35functions copy and concatenate strings respectively.
36They are designed
37to be safer, more consistent, and less error prone replacements for
38.Xr strncpy 3
39and
40.Xr strncat 3 .
41Unlike those functions,
42.Fn strlcpy
43and
44.Fn strlcat
45take the full size of the buffer (not just the length) and guarantee to
46NUL-terminate the result (as long as
47.Fa size
48is larger than 0 or, in the case of
49.Fn strlcat ,
50as long as there is at least one byte free in
51.Fa dst ) .
52Note that you should include a byte for the NUL in
53.Fa size .
54Also note that
55.Fn strlcpy
56and
57.Fn strlcat
58only operate on true
59.Dq C
60strings.
61This means that for
62.Fn strlcpy
63.Fa src
64must be NUL-terminated and for
65.Fn strlcat
66both
67.Fa src
68and
69.Fa dst
70must be NUL-terminated.
71.Pp
72The
73.Fn strlcpy
74function copies up to
75.Fa size
76- 1 characters from the NUL-terminated string
77.Fa src
78to
79.Fa dst ,
80NUL-terminating the result.
81.Pp
82The
83.Fn strlcat
84function appends the NUL-terminated string
85.Fa src
86to the end of
87.Fa dst .
88It will append at most
89.Fa size
90- strlen(dst) - 1 bytes, NUL-terminating the result.
91.Sh RETURN VALUES
92The
93.Fn strlcpy
94and
95.Fn strlcat
96functions return the total length of the string they tried to create.
97For
98.Fn strlcpy
99that means the length of
100.Fa src .
101For
102.Fn strlcat
103that means the initial length of
104.Fa dst
105plus
106the length of
107.Fa src .
108While this may seem somewhat confusing it was done to make
109truncation detection simple.
110.Pp
111Note however, that if
112.Fn strlcat
113traverses
114.Fa size
115characters without finding a NUL, the length of the string is considered
116to be
117.Fa size
118and the destination string will not be NUL-terminated (since there was
119no space for the NUL).
120This keeps
121.Fn strlcat
122from running off the end of a string.
123In practice this should not happen (as it means that either
124.Fa size
125is incorrect or that
126.Fa dst
127is not a proper
128.Dq C
129string).
130The check exists to prevent potential security problems in incorrect code.
131.Sh EXAMPLES
132The following code fragment illustrates the simple case:
133.Bd -literal -offset indent
134char *s, *p, buf[BUFSIZ];
135
136\&...
137
138(void)strlcpy(buf, s, sizeof(buf));
139(void)strlcat(buf, p, sizeof(buf));
140.Ed
141.Pp
142To detect truncation, perhaps while building a pathname, something
143like the following might be used:
144.Bd -literal -offset indent
145char *dir, *file, pname[MAXPATHLEN];
146
147\&...
148
149if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
150 goto toolong;
151if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
152 goto toolong;
153.Ed
154.Pp
155Since we know how many characters we copied the first time, we can
156speed things up a bit by using a copy instead of an append:
157.Bd -literal -offset indent
158char *dir, *file, pname[MAXPATHLEN];
159size_t n;
160
161\&...
162
163n = strlcpy(pname, dir, sizeof(pname));
164if (n >= sizeof(pname))
165 goto toolong;
166if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
167 goto toolong;
168.Ed
169.Pp
170However, one may question the validity of such optimizations, as they
171defeat the whole purpose of
172.Fn strlcpy
173and
174.Fn strlcat .
175As a matter of fact, the first version of this manual page got it wrong.
176.Sh SEE ALSO
177.Xr snprintf 3 ,
178.Xr strncat 3 ,
179.Xr strncpy 3
diff --git a/src/lib/libc/string/strlcpy.c b/src/lib/libc/string/strlcpy.c
new file mode 100644
index 0000000000..09a9c2b360
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.c
@@ -0,0 +1,55 @@
1/* $OpenBSD: strlcpy.c,v 1.9 2005/03/30 20:13:52 otto Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20static char *rcsid = "$OpenBSD: strlcpy.c,v 1.9 2005/03/30 20:13:52 otto Exp $";
21#endif /* LIBC_SCCS and not lint */
22
23#include <sys/types.h>
24#include <string.h>
25
26/*
27 * Copy src to string dst of size siz. At most siz-1 characters
28 * will be copied. Always NUL terminates (unless siz == 0).
29 * Returns strlen(src); if retval >= siz, truncation occurred.
30 */
31size_t
32strlcpy(char *dst, const char *src, size_t siz)
33{
34 char *d = dst;
35 const char *s = src;
36 size_t n = siz;
37
38 /* Copy as many bytes as will fit */
39 if (n != 0 && --n != 0) {
40 do {
41 if ((*d++ = *s++) == 0)
42 break;
43 } while (--n != 0);
44 }
45
46 /* Not enough room in dst, add NUL and traverse rest of src */
47 if (n == 0) {
48 if (siz != 0)
49 *d = '\0'; /* NUL-terminate dst */
50 while (*s++)
51 ;
52 }
53
54 return(s - src - 1); /* count does not include NUL */
55}
diff --git a/src/lib/libc/string/strlen.3 b/src/lib/libc/string/strlen.3
new file mode 100644
index 0000000000..32bbc88542
--- /dev/null
+++ b/src/lib/libc/string/strlen.3
@@ -0,0 +1,61 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: strlen.3,v 1.5 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRLEN 3
36.Os
37.Sh NAME
38.Nm strlen
39.Nd find length of a string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft size_t
43.Fn strlen "const char *s"
44.Sh DESCRIPTION
45The
46.Fn strlen
47function computes the length of the string
48.Fa s .
49.Sh RETURN VALUES
50The
51.Fn strlen
52function returns the number of characters that precede the terminating
53.Tn NUL
54character.
55.Sh SEE ALSO
56.Xr string 3
57.Sh STANDARDS
58The
59.Fn strlen
60function conforms to
61.St -ansiC .
diff --git a/src/lib/libc/string/strlen.c b/src/lib/libc/string/strlen.c
new file mode 100644
index 0000000000..298a9966a3
--- /dev/null
+++ b/src/lib/libc/string/strlen.c
@@ -0,0 +1,51 @@
1/* $OpenBSD: strlen.c,v 1.6 2003/06/11 21:08:16 deraadt 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: strlen.c,v 1.6 2003/06/11 21:08:16 deraadt Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42size_t
43strlen(const char *str)
44{
45 const char *s;
46
47 for (s = str; *s; ++s)
48 ;
49 return (s - str);
50}
51
diff --git a/src/lib/libc/string/strmode.3 b/src/lib/libc/string/strmode.3
new file mode 100644
index 0000000000..3a7a4bb3fa
--- /dev/null
+++ b/src/lib/libc/string/strmode.3
@@ -0,0 +1,159 @@
1.\" $OpenBSD: strmode.3,v 1.12 2005/02/25 03:12:44 cloder 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.\" @(#)strmode.3 8.3 (Berkeley) 7/28/94
31.\"
32.Dd July 28, 1994
33.Dt STRMODE 3
34.Os
35.Sh NAME
36.Nm strmode
37.Nd convert inode status information into a symbolic string
38.Sh SYNOPSIS
39.Fd #include <string.h>
40.Ft void
41.Fn strmode "mode_t mode" "char *bp"
42.Sh DESCRIPTION
43The
44.Fn strmode
45function converts a file
46.Fa mode
47(the type and permission information associated with an inode, see
48.Xr stat 2 )
49into a symbolic string which is stored in the location referenced by
50.Fa bp .
51This stored string is eleven characters in length plus a trailing NUL byte.
52.Pp
53The first character is the inode type, and will be one of the following:
54.Pp
55.Bl -tag -width flag -offset indent -compact
56.It \-
57regular file
58.It b
59block special
60.It c
61character special
62.It d
63directory
64.It l
65symbolic link
66.It p
67FIFO
68.It s
69socket
70.It w
71whiteout
72.It \&?
73unknown inode type
74.El
75.Pp
76The next nine characters encode three sets of permissions, in three
77characters each.
78The first three characters are the permissions for the owner of the
79file, the second three for the group the file belongs to, and the
80third for the
81.Dq other ,
82or default, set of users.
83.Pp
84Permission checking is done as specifically as possible.
85If read permission is denied to the owner of a file in the first set
86of permissions, the owner of the file will not be able to read the file.
87This is true even if the owner is in the file's group and the group
88permissions allow reading or the
89.Dq other
90permissions allow reading.
91.Pp
92If the first character of the three character set is an
93.Sq r ,
94the file is readable for that set of users; if a dash
95.Pq Ql - ,
96it is not readable.
97.Pp
98If the second character of the three character set is a
99.Sq w ,
100the file is writable for that set of users; if a dash
101.Pq Ql - ,
102it is not writable.
103.Pp
104The third character is the first of the following characters that apply:
105.Bl -tag -width xxxx
106.It S
107If the character is part of the owner permissions and the file is not
108executable or the directory is not searchable by the owner, and the
109set-user-ID bit is set.
110.It S
111If the character is part of the group permissions and the file is not
112executable or the directory is not searchable by the group, and the
113set-group-ID bit is set.
114.It T
115If the character is part of the other permissions and the file is not
116executable or the directory is not searchable by others, and the
117.Dq sticky
118.Pq Dv S_ISVTX
119bit is set.
120.It s
121If the character is part of the owner permissions and the file is
122executable or the directory searchable by the owner, and the set-user-ID
123bit is set.
124.It s
125If the character is part of the group permissions and the file is
126executable or the directory searchable by the group, and the set-group-ID
127bit is set.
128.It t
129If the character is part of the other permissions and the file is
130executable or the directory searchable by others, and the
131.Dq sticky
132.Pq Dv S_ISVTX
133bit is set.
134.It x
135The file is executable or the directory is searchable.
136.It \-
137None of the above apply.
138.El
139.Pp
140The last character is a plus sign
141.Pq Ql +
142if there are any alternate
143or additional access control methods associated with the inode, otherwise
144it will be a space.
145.Sh RETURN VALUES
146The
147.Fn strmode
148function always returns 0.
149.Sh SEE ALSO
150.Xr chmod 1 ,
151.Xr find 1 ,
152.Xr stat 2 ,
153.Xr getmode 3 ,
154.Xr setmode 3
155.Sh HISTORY
156The
157.Fn strmode
158function first appeared in
159.Bx 4.4 .
diff --git a/src/lib/libc/string/strmode.c b/src/lib/libc/string/strmode.c
new file mode 100644
index 0000000000..bd78403cb2
--- /dev/null
+++ b/src/lib/libc/string/strmode.c
@@ -0,0 +1,148 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strmode.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <string.h>
37
38/* XXX mode should be mode_t */
39
40void
41strmode(int mode, char *p)
42{
43 /* print type */
44 switch (mode & S_IFMT) {
45 case S_IFDIR: /* directory */
46 *p++ = 'd';
47 break;
48 case S_IFCHR: /* character special */
49 *p++ = 'c';
50 break;
51 case S_IFBLK: /* block special */
52 *p++ = 'b';
53 break;
54 case S_IFREG: /* regular */
55 *p++ = '-';
56 break;
57 case S_IFLNK: /* symbolic link */
58 *p++ = 'l';
59 break;
60 case S_IFSOCK: /* socket */
61 *p++ = 's';
62 break;
63#ifdef S_IFIFO
64 case S_IFIFO: /* fifo */
65 *p++ = 'p';
66 break;
67#endif
68#ifdef S_IFWHT
69 case S_IFWHT: /* whiteout */
70 *p++ = 'w';
71 break;
72#endif
73 default: /* unknown */
74 *p++ = '?';
75 break;
76 }
77 /* usr */
78 if (mode & S_IRUSR)
79 *p++ = 'r';
80 else
81 *p++ = '-';
82 if (mode & S_IWUSR)
83 *p++ = 'w';
84 else
85 *p++ = '-';
86 switch (mode & (S_IXUSR | S_ISUID)) {
87 case 0:
88 *p++ = '-';
89 break;
90 case S_IXUSR:
91 *p++ = 'x';
92 break;
93 case S_ISUID:
94 *p++ = 'S';
95 break;
96 case S_IXUSR | S_ISUID:
97 *p++ = 's';
98 break;
99 }
100 /* group */
101 if (mode & S_IRGRP)
102 *p++ = 'r';
103 else
104 *p++ = '-';
105 if (mode & S_IWGRP)
106 *p++ = 'w';
107 else
108 *p++ = '-';
109 switch (mode & (S_IXGRP | S_ISGID)) {
110 case 0:
111 *p++ = '-';
112 break;
113 case S_IXGRP:
114 *p++ = 'x';
115 break;
116 case S_ISGID:
117 *p++ = 'S';
118 break;
119 case S_IXGRP | S_ISGID:
120 *p++ = 's';
121 break;
122 }
123 /* other */
124 if (mode & S_IROTH)
125 *p++ = 'r';
126 else
127 *p++ = '-';
128 if (mode & S_IWOTH)
129 *p++ = 'w';
130 else
131 *p++ = '-';
132 switch (mode & (S_IXOTH | S_ISVTX)) {
133 case 0:
134 *p++ = '-';
135 break;
136 case S_IXOTH:
137 *p++ = 'x';
138 break;
139 case S_ISVTX:
140 *p++ = 'T';
141 break;
142 case S_IXOTH | S_ISVTX:
143 *p++ = 't';
144 break;
145 }
146 *p++ = ' '; /* will be a '+' if ACL's implemented */
147 *p = '\0';
148}
diff --git a/src/lib/libc/string/strncat.c b/src/lib/libc/string/strncat.c
new file mode 100644
index 0000000000..05d35e0900
--- /dev/null
+++ b/src/lib/libc/string/strncat.c
@@ -0,0 +1,60 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: strncat.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Concatenate src on the end of dst. At most strlen(dst)+n+1 bytes
41 * are written at dst (at most n+1 bytes being appended). Return dst.
42 */
43char *
44strncat(char *dst, const char *src, size_t n)
45{
46 if (n != 0) {
47 char *d = dst;
48 const char *s = src;
49
50 while (*d != 0)
51 d++;
52 do {
53 if ((*d = *s++) == 0)
54 break;
55 d++;
56 } while (--n != 0);
57 *d = 0;
58 }
59 return (dst);
60}
diff --git a/src/lib/libc/string/strncmp.c b/src/lib/libc/string/strncmp.c
new file mode 100644
index 0000000000..ddab42dc75
--- /dev/null
+++ b/src/lib/libc/string/strncmp.c
@@ -0,0 +1,55 @@
1/* $OpenBSD: strncmp.c,v 1.6 2004/11/28 07:16:54 mickey Exp $ */
2
3/*
4 * Copyright (c) 1989 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#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: strncmp.c,v 1.6 2004/11/28 07:16:54 mickey Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <string.h>
38#else
39#include <lib/libkern/libkern.h>
40#endif
41
42int
43strncmp(const char *s1, const char *s2, size_t n)
44{
45
46 if (n == 0)
47 return (0);
48 do {
49 if (*s1 != *s2++)
50 return (*(unsigned char *)s1 - *(unsigned char *)--s2);
51 if (*s1++ == 0)
52 break;
53 } while (--n != 0);
54 return (0);
55}
diff --git a/src/lib/libc/string/strncpy.c b/src/lib/libc/string/strncpy.c
new file mode 100644
index 0000000000..d73008c6db
--- /dev/null
+++ b/src/lib/libc/string/strncpy.c
@@ -0,0 +1,66 @@
1/* $OpenBSD: strncpy.c,v 1.5 2004/11/28 07:16:54 mickey Exp $ */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
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#if defined(LIBC_SCCS) && !defined(lint)
36static char *rcsid = "$OpenBSD: strncpy.c,v 1.5 2004/11/28 07:16:54 mickey Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#if !defined(_KERNEL) && !defined(_STANDALONE)
40#include <string.h>
41#else
42#include <lib/libkern/libkern.h>
43#endif
44
45/*
46 * Copy src to dst, truncating or null-padding to always copy n bytes.
47 * Return dst.
48 */
49char *
50strncpy(char *dst, const char *src, size_t n)
51{
52 if (n != 0) {
53 char *d = dst;
54 const char *s = src;
55
56 do {
57 if ((*d++ = *s++) == 0) {
58 /* NUL pad the remaining n-1 bytes */
59 while (--n != 0)
60 *d++ = 0;
61 break;
62 }
63 } while (--n != 0);
64 }
65 return (dst);
66}
diff --git a/src/lib/libc/string/strpbrk.3 b/src/lib/libc/string/strpbrk.3
new file mode 100644
index 0000000000..e91776a0ca
--- /dev/null
+++ b/src/lib/libc/string/strpbrk.3
@@ -0,0 +1,72 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: strpbrk.3,v 1.7 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRPBRK 3
36.Os
37.Sh NAME
38.Nm strpbrk
39.Nd locate multiple characters in string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft char *
43.Fn strpbrk "const char *s" "const char *charset"
44.Sh DESCRIPTION
45The
46.Fn strpbrk
47function locates in the NUL-terminated string
48.Fa s
49the first occurrence of any character in the string
50.Fa charset
51and returns a pointer to this character.
52If no characters from
53.Fa charset
54occur anywhere in
55.Fa s ,
56.Fn strpbrk
57returns
58.Dv NULL .
59.Sh SEE ALSO
60.Xr memchr 3 ,
61.Xr strchr 3 ,
62.Xr strcspn 3 ,
63.Xr strrchr 3 ,
64.Xr strsep 3 ,
65.Xr strspn 3 ,
66.Xr strstr 3 ,
67.Xr strtok 3
68.Sh STANDARDS
69The
70.Fn strpbrk
71function conforms to
72.St -ansiC .
diff --git a/src/lib/libc/string/strpbrk.c b/src/lib/libc/string/strpbrk.c
new file mode 100644
index 0000000000..024c42bdc3
--- /dev/null
+++ b/src/lib/libc/string/strpbrk.c
@@ -0,0 +1,51 @@
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strpbrk.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35
36/*
37 * Find the first occurrence in s1 of a character in s2 (excluding NUL).
38 */
39char *
40strpbrk(const char *s1, const char *s2)
41{
42 const char *scanp;
43 int c, sc;
44
45 while ((c = *s1++) != 0) {
46 for (scanp = s2; (sc = *scanp++) != 0;)
47 if (sc == c)
48 return ((char *)(s1 - 1));
49 }
50 return (NULL);
51}
diff --git a/src/lib/libc/string/strrchr.3 b/src/lib/libc/string/strrchr.3
new file mode 100644
index 0000000000..d7e0eeff85
--- /dev/null
+++ b/src/lib/libc/string/strrchr.3
@@ -0,0 +1,104 @@
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: strrchr.3,v 1.7 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRRCHR 3
36.Os
37.Sh NAME
38.Nm strrchr ,
39.Nm rindex
40.Nd locate last occurrence of a character in a string
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strrchr "const char *s" "int c"
45.Ft char *
46.Fn rindex "const char *s" "int c"
47.Sh DESCRIPTION
48The
49.Fn strrchr
50function locates the last occurrence of the character
51.Fa c
52in the string
53.Fa s .
54The terminating
55.Tn NUL
56character is considered part of the string.
57If
58.Fa c
59is
60.Ql \e0 ,
61.Fn strrchr
62locates the terminating
63.Ql \e0 .
64.Pp
65The
66.Fn rindex
67function is an old synonym for
68.Fn strrchr .
69.Sh RETURN VALUES
70The
71.Fn strrchr
72function returns a pointer to the located character or
73.Dv NULL
74if the character does not appear in the string.
75.Sh EXAMPLES
76After the following call to
77.Fn strrchr ,
78.Va p
79will point to the string
80.Qq obar :
81.Bd -literal -offset indent
82char *p;
83char *s = "foobar";
84
85p = strrchr(s, 'o');
86.Ed
87.Sh SEE ALSO
88.Xr memchr 3 ,
89.Xr strchr 3 ,
90.Xr strcspn 3 ,
91.Xr strpbrk 3 ,
92.Xr strsep 3 ,
93.Xr strspn 3 ,
94.Xr strstr 3 ,
95.Xr strtok 3
96.Sh STANDARDS
97The
98.Fn strrchr
99function conforms to
100.St -ansiC .
101.Pp
102The
103.Fn rindex
104function is deprecated and shouldn't be used in new code.
diff --git a/src/lib/libc/string/strsep.3 b/src/lib/libc/string/strsep.3
new file mode 100644
index 0000000000..ddcc22916a
--- /dev/null
+++ b/src/lib/libc/string/strsep.3
@@ -0,0 +1,112 @@
1.\" $OpenBSD: strsep.3,v 1.11 2003/06/02 20:18:38 millert Exp $
2.\"
3.\" Copyright (c) 1990, 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.\" 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.\" @(#)strsep.3 8.1 (Berkeley) 6/9/93
34.\"
35.Dd June 9, 1993
36.Dt STRSEP 3
37.Os
38.Sh NAME
39.Nm strsep
40.Nd separate strings
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strsep "char **stringp" "const char *delim"
45.Sh DESCRIPTION
46The
47.Fn strsep
48function locates, in the string referenced by
49.Fa *stringp ,
50the first occurrence of any character in the string
51.Fa delim
52(or the terminating
53.Ql \e0
54character) and replaces it with a
55.Ql \e0 .
56The location of the next character after the delimiter character
57(or
58.Dv NULL ,
59if the end of the string was reached) is stored in
60.Fa *stringp .
61The original value of
62.Fa *stringp
63is returned.
64.Pp
65An
66.Dq empty
67field, i.e., one caused by two adjacent delimiter characters,
68can be detected by comparing the location referenced by the pointer returned
69by
70.Fn strsep
71to
72.Ql \e0 .
73.Pp
74If
75.Fa *stringp
76is initially
77.Dv NULL ,
78.Fn strsep
79returns
80.Dv NULL .
81.Sh EXAMPLES
82The following uses
83.Fn strsep
84to parse a string, containing tokens delimited by whitespace, into an
85argument vector:
86.Bd -literal -offset indent
87char **ap, *argv[10], *inputstring;
88
89for (ap = argv; ap < &argv[9] &&
90 (*ap = strsep(&inputstring, " \et")) != NULL;) {
91 if (**ap != '\e0')
92 ap++;
93}
94*ap = NULL;
95.Ed
96.Sh HISTORY
97The
98.Fn strsep
99function is intended as a replacement for the
100.Fn strtok
101function.
102While the
103.Fn strtok
104function should be preferred for portability reasons (it conforms to
105.St -ansiC )
106it is unable to handle empty fields, i.e., detect fields delimited by
107two adjacent delimiter characters, or to be used for more than a single
108string at a time.
109The
110.Fn strsep
111function first appeared in
112.Bx 4.4 .
diff --git a/src/lib/libc/string/strsep.c b/src/lib/libc/string/strsep.c
new file mode 100644
index 0000000000..337d78e466
--- /dev/null
+++ b/src/lib/libc/string/strsep.c
@@ -0,0 +1,79 @@
1/* $OpenBSD: strsep.c,v 1.5 2003/06/11 21:08:16 deraadt 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 <string.h>
33#include <stdio.h>
34
35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0
37static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
38#else
39static char *rcsid = "$OpenBSD: strsep.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
40#endif
41#endif /* LIBC_SCCS and not lint */
42
43/*
44 * Get next token from string *stringp, where tokens are possibly-empty
45 * strings separated by characters from delim.
46 *
47 * Writes NULs into the string at *stringp to end tokens.
48 * delim need not remain constant from call to call.
49 * On return, *stringp points past the last NUL written (if there might
50 * be further tokens), or is NULL (if there are definitely no more tokens).
51 *
52 * If *stringp is NULL, strsep returns NULL.
53 */
54char *
55strsep(char **stringp, const char *delim)
56{
57 char *s;
58 const char *spanp;
59 int c, sc;
60 char *tok;
61
62 if ((s = *stringp) == NULL)
63 return (NULL);
64 for (tok = s;;) {
65 c = *s++;
66 spanp = delim;
67 do {
68 if ((sc = *spanp++) == c) {
69 if (c == 0)
70 s = NULL;
71 else
72 s[-1] = 0;
73 *stringp = s;
74 return (tok);
75 }
76 } while (sc != 0);
77 }
78 /* NOTREACHED */
79}
diff --git a/src/lib/libc/string/strsignal.3 b/src/lib/libc/string/strsignal.3
new file mode 100644
index 0000000000..b1082c2dd0
--- /dev/null
+++ b/src/lib/libc/string/strsignal.3
@@ -0,0 +1,56 @@
1.\" Copyright (c) 1980, 1991 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: strsignal.3,v 1.4 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRSIGNAL 3
36.Os
37.Sh NAME
38.Nm strsignal
39.Nd get signal description string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft char *
43.Fn strsignal "int sig"
44.Sh DESCRIPTION
45The
46.Fn strsignal
47function returns a pointer to the language-dependent string describing
48a signal.
49.Pp
50The array pointed to is not to be modified by the program, but may be
51overwritten by subsequent calls to
52.Fn strsignal .
53.Sh SEE ALSO
54.Xr intro 2 ,
55.Xr psignal 3 ,
56.Xr setlocale 3
diff --git a/src/lib/libc/string/strsignal.c b/src/lib/libc/string/strsignal.c
new file mode 100644
index 0000000000..afe0deb272
--- /dev/null
+++ b/src/lib/libc/string/strsignal.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strsignal.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35#include <limits.h>
36
37extern char *__strsignal(int, char *);
38
39char *
40strsignal(int sig)
41{
42 static char buf[NL_TEXTMAX];
43
44 return __strsignal(sig, buf);
45}
diff --git a/src/lib/libc/string/strspn.3 b/src/lib/libc/string/strspn.3
new file mode 100644
index 0000000000..5dc7e9746a
--- /dev/null
+++ b/src/lib/libc/string/strspn.3
@@ -0,0 +1,84 @@
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: strspn.3,v 1.8 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRSPN 3
36.Os
37.Sh NAME
38.Nm strspn
39.Nd span a string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft size_t
43.Fn strspn "const char *s" "const char *charset"
44.Sh DESCRIPTION
45The
46.Fn strspn
47function spans the initial part of the NUL-terminated string
48.Fa s
49as long as the characters from
50.Fa s
51occur in string
52.Fa charset .
53.Sh RETURN VALUES
54The
55.Fn strspn
56function returns the number of characters spanned.
57.Sh EXAMPLES
58The following call to
59.Fn strspn
60will return 3, since the first three characters of string
61.Fa s
62are part of string
63.Fa charset :
64.Bd -literal -offset indent
65char *s = "foobar";
66char *charset = "of";
67size_t span;
68
69span = strspn(s, charset);
70.Ed
71.Sh SEE ALSO
72.Xr memchr 3 ,
73.Xr strchr 3 ,
74.Xr strcspn 3 ,
75.Xr strpbrk 3 ,
76.Xr strrchr 3 ,
77.Xr strsep 3 ,
78.Xr strstr 3 ,
79.Xr strtok 3
80.Sh STANDARDS
81The
82.Fn strspn
83function conforms to
84.St -ansiC .
diff --git a/src/lib/libc/string/strspn.c b/src/lib/libc/string/strspn.c
new file mode 100644
index 0000000000..d51a8cd3e6
--- /dev/null
+++ b/src/lib/libc/string/strspn.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strspn.c,v 1.4 2003/06/11 21:08:29 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35
36/*
37 * Span the string s2 (skip characters that are in s2).
38 */
39size_t
40strspn(const char *s1, const char *s2)
41{
42 const char *p = s1, *spanp;
43 char c, sc;
44
45 /*
46 * Skip any characters in s2, excluding the terminating \0.
47 */
48cont:
49 c = *p++;
50 for (spanp = s2; (sc = *spanp++) != 0;)
51 if (sc == c)
52 goto cont;
53 return (p - 1 - s1);
54}
diff --git a/src/lib/libc/string/strstr.3 b/src/lib/libc/string/strstr.3
new file mode 100644
index 0000000000..2c8fa1888f
--- /dev/null
+++ b/src/lib/libc/string/strstr.3
@@ -0,0 +1,87 @@
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: strstr.3,v 1.8 2005/03/30 03:04:19 deraadt Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRSTR 3
36.Os
37.Sh NAME
38.Nm strstr , strcasestr
39.Nd locate a substring in a string
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft char *
43.Fn strstr "const char *big" "const char *little"
44.Ft char *
45.Fn strcasestr "const char *big" "const char *little"
46.Sh DESCRIPTION
47The
48.Fn strstr
49function locates the first occurrence of the NUL-terminated string
50.Fa little
51in the NUL-terminated string
52.Fa big .
53.Pp
54The
55.Fn strcasestr
56function is similar to
57.Fn strstr
58but ignores the case of both strings.
59.Pp
60If
61.Fa little
62is an empty string,
63.Fa big
64is returned;
65if
66.Fa little
67occurs nowhere in
68.Fa big ,
69.Dv NULL
70is returned;
71otherwise a pointer to the first character of the first occurrence of
72.Fa little
73is returned.
74.Sh SEE ALSO
75.Xr memchr 3 ,
76.Xr strchr 3 ,
77.Xr strcspn 3 ,
78.Xr strpbrk 3 ,
79.Xr strrchr 3 ,
80.Xr strsep 3 ,
81.Xr strspn 3 ,
82.Xr strtok 3
83.Sh STANDARDS
84The
85.Fn strstr
86function conforms to
87.St -ansiC .
diff --git a/src/lib/libc/string/strstr.c b/src/lib/libc/string/strstr.c
new file mode 100644
index 0000000000..e6a94c5ce6
--- /dev/null
+++ b/src/lib/libc/string/strstr.c
@@ -0,0 +1,59 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: strstr.c,v 1.4 2003/06/11 21:08:16 deraadt Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Find the first occurrence of find in s.
41 */
42char *
43strstr(const char *s, const char *find)
44{
45 char c, sc;
46 size_t len;
47
48 if ((c = *find++) != 0) {
49 len = strlen(find);
50 do {
51 do {
52 if ((sc = *s++) == 0)
53 return (NULL);
54 } while (sc != c);
55 } while (strncmp(s, find, len) != 0);
56 s--;
57 }
58 return ((char *)s);
59}
diff --git a/src/lib/libc/string/strtok.3 b/src/lib/libc/string/strtok.3
new file mode 100644
index 0000000000..03a93980ab
--- /dev/null
+++ b/src/lib/libc/string/strtok.3
@@ -0,0 +1,152 @@
1.\" Copyright (c) 1988, 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: strtok.3,v 1.18 2005/02/25 03:12:44 cloder Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRTOK 3
36.Os
37.Sh NAME
38.Nm strtok ,
39.Nm strtok_r
40.Nd string token operations
41.Sh SYNOPSIS
42.Fd #include <string.h>
43.Ft char *
44.Fn strtok "char *str" "const char *sep"
45.Ft char *
46.Fn strtok_r "char *str" "const char *sep" "char **last"
47.Sh DESCRIPTION
48.Bf -symbolic
49This interface is obsoleted by
50.Xr strsep 3 .
51.Ef
52.Pp
53The
54.Fn strtok
55function is used to isolate sequential tokens in a NUL-terminated string,
56.Fa str .
57These tokens are separated in the string by at least one of the
58characters in
59.Fa sep .
60The first time that
61.Fn strtok
62is called,
63.Fa str
64should be specified; subsequent calls, wishing to obtain further tokens
65from the same string, should pass a null pointer instead.
66The separator string,
67.Fa sep ,
68must be supplied each time, and may change between calls.
69.Pp
70The
71.Fn strtok_r
72function is a version of
73.Fn strtok
74that takes an explicit context argument and is reentrant.
75.Pp
76The
77.Fn strtok
78and
79.Fn strtok_r
80functions return a pointer to the beginning of each subsequent token
81in the string, after replacing the separator character itself with an
82.Tn ASCII NUL
83character.
84When no more tokens remain, a null pointer is returned.
85.Pp
86Since
87.Fn strtok
88and
89.Fn strtok_r
90modify the string,
91.Fa str
92should not point to an area in the initialized data segment.
93.Sh EXAMPLES
94The following will construct an array of pointers to each individual word in
95the string
96.Va s :
97.Bd -literal -offset indent
98#define MAXTOKENS 128
99
100char s[512], *p, *tokens[MAXTOKENS];
101char *last;
102int i = 0;
103
104snprintf(s, sizeof(s), "cat dog horse cow");
105
106for ((p = strtok_r(s, " ", &last)); p;
107 (p = strtok_r(NULL, " ", &last))) {
108 if (i < MAXTOKENS - 1)
109 tokens[i++] = p;
110}
111tokens[i] = NULL;
112.Ed
113.Pp
114That is,
115.Li tokens[0]
116will point to
117.Qq cat ,
118.Li tokens[1]
119will point to
120.Qq dog ,
121.Li tokens[2]
122will point to
123.Qq horse ,
124and
125.Li tokens[3]
126will point to
127.Qq cow .
128.Sh SEE ALSO
129.Xr memchr 3 ,
130.Xr strchr 3 ,
131.Xr strcspn 3 ,
132.Xr strpbrk 3 ,
133.Xr strrchr 3 ,
134.Xr strsep 3 ,
135.Xr strspn 3 ,
136.Xr strstr 3
137.Sh STANDARDS
138The
139.Fn strtok
140function conforms to
141.St -ansiC .
142.Sh BUGS
143The System V
144.Fn strtok ,
145if handed a string containing only delimiter characters,
146will not alter the next starting point, so that a call to
147.Fn strtok
148with a different (or empty) delimiter string
149may return a non-null value.
150Since this implementation always alters the next starting point,
151such a sequence of calls would always return
152.Dv NULL .
diff --git a/src/lib/libc/string/strtok.c b/src/lib/libc/string/strtok.c
new file mode 100644
index 0000000000..6498eac8cc
--- /dev/null
+++ b/src/lib/libc/string/strtok.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strtok.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <string.h>
35
36char *
37strtok(char *s, const char *delim)
38{
39 static char *last;
40
41 return strtok_r(s, delim, &last);
42}
43
44char *
45strtok_r(char *s, const char *delim, char **last)
46{
47 char *spanp;
48 int c, sc;
49 char *tok;
50
51
52 if (s == NULL && (s = *last) == NULL)
53 return (NULL);
54
55 /*
56 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
57 */
58cont:
59 c = *s++;
60 for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
61 if (c == sc)
62 goto cont;
63 }
64
65 if (c == 0) { /* no non-delimiter characters */
66 *last = NULL;
67 return (NULL);
68 }
69 tok = s - 1;
70
71 /*
72 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
73 * Note that delim must have one NUL; we stop if we see that, too.
74 */
75 for (;;) {
76 c = *s++;
77 spanp = (char *)delim;
78 do {
79 if ((sc = *spanp++) == c) {
80 if (c == 0)
81 s = NULL;
82 else
83 s[-1] = 0;
84 *last = s;
85 return (tok);
86 }
87 } while (sc != 0);
88 }
89 /* NOTREACHED */
90}
diff --git a/src/lib/libc/string/strxfrm.3 b/src/lib/libc/string/strxfrm.3
new file mode 100644
index 0000000000..edf2bfb8a0
--- /dev/null
+++ b/src/lib/libc/string/strxfrm.3
@@ -0,0 +1,62 @@
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: strxfrm.3,v 1.4 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRXFRM 3
36.Os
37.Sh NAME
38.Nm strxfrm
39.Nd transform a string under locale
40.Sh SYNOPSIS
41.Fd #include <string.h>
42.Ft size_t
43.Fn strxfrm "char *dst" "const char *src" "size_t n"
44.Sh DESCRIPTION
45The
46.Fn strxfrm
47function does something horrible (see
48.Tn ANSI
49standard).
50In this implementation it just copies.
51.Sh SEE ALSO
52.Xr bcmp 3 ,
53.Xr memcmp 3 ,
54.\" .Xr setlocale 3 ,
55.Xr strcasecmp 3 ,
56.Xr strcmp 3 ,
57.Xr strcoll 3
58.Sh STANDARDS
59The
60.Fn strxfrm
61function conforms to
62.St -ansiC .
diff --git a/src/lib/libc/string/strxfrm.c b/src/lib/libc/string/strxfrm.c
new file mode 100644
index 0000000000..a2e2dbc440
--- /dev/null
+++ b/src/lib/libc/string/strxfrm.c
@@ -0,0 +1,54 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: strxfrm.c,v 1.5 2003/09/06 22:43:12 tedu Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <string.h>
38
39/*
40 * Transform src, storing the result in dst, such that
41 * strcmp() on transformed strings returns what strcoll()
42 * on the original untransformed strings would return.
43 */
44size_t
45strxfrm(char *dst, const char *src, size_t n)
46{
47
48 /*
49 * Since locales are unimplemented, this is just a copy.
50 */
51 if (n == 0)
52 return (strlen(src));
53 return (strlcpy(dst, src, n));
54}
diff --git a/src/lib/libc/string/swab.3 b/src/lib/libc/string/swab.3
new file mode 100644
index 0000000000..abeff903de
--- /dev/null
+++ b/src/lib/libc/string/swab.3
@@ -0,0 +1,61 @@
1.\" Copyright (c) 1990, 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: swab.3,v 1.5 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd May 1, 1991
31.Dt SWAB 3
32.Os
33.Sh NAME
34.Nm swab
35.Nd swap adjacent bytes
36.Sh SYNOPSIS
37.Fd #include <unistd.h>
38.Ft void
39.Fn swab "const void *src" "void *dst" "size_t len"
40.Sh DESCRIPTION
41The function
42.Fn swab
43copies
44.Fa len
45bytes from the location referenced by
46.Fa src
47to the location referenced by
48.Fa dst ,
49swapping adjacent bytes.
50.Pp
51The argument
52.Fa len
53must be an even number.
54.Sh SEE ALSO
55.Xr bzero 3 ,
56.Xr memset 3
57.Sh HISTORY
58A
59.Fn swab
60function appeared in
61.At v7 .
diff --git a/src/lib/libc/string/swab.c b/src/lib/libc/string/swab.c
new file mode 100644
index 0000000000..0129561aa3
--- /dev/null
+++ b/src/lib/libc/string/swab.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Jeffrey Mogul.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: swab.c,v 1.6 2005/03/30 20:13:52 otto Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <unistd.h>
38
39void
40swab(const void *from, void *to, size_t len)
41{
42 unsigned long temp;
43 int n;
44 char *fp, *tp;
45
46 n = (len >> 1) + 1;
47 fp = (char *)from;
48 tp = (char *)to;
49#define STEP temp = *fp++,*tp++ = *fp++,*tp++ = temp
50 /* round to multiple of 8 */
51 while ((--n) & 07)
52 STEP;
53 n >>= 3;
54 while (--n >= 0) {
55 STEP; STEP; STEP; STEP;
56 STEP; STEP; STEP; STEP;
57 }
58}
diff --git a/src/lib/libc/string/wcscat.c b/src/lib/libc/string/wcscat.c
new file mode 100644
index 0000000000..69c8c0c251
--- /dev/null
+++ b/src/lib/libc/string/wcscat.c
@@ -0,0 +1,56 @@
1/* $OpenBSD: wcscat.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcscat.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcscat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcscat.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcscat(s1, s2)
40 wchar_t *s1;
41 const wchar_t *s2;
42{
43 wchar_t *p;
44 wchar_t *q;
45 const wchar_t *r;
46
47 p = s1;
48 while (*p)
49 p++;
50 q = p;
51 r = s2;
52 while (*r)
53 *q++ = *r++;
54 *q = '\0';
55 return s1;
56}
diff --git a/src/lib/libc/string/wcschr.c b/src/lib/libc/string/wcschr.c
new file mode 100644
index 0000000000..eb4e65a85d
--- /dev/null
+++ b/src/lib/libc/string/wcschr.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: wcschr.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcschr.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcschr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcschr.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcschr(s, c)
40 const wchar_t *s;
41 wchar_t c;
42{
43 const wchar_t *p;
44
45 p = s;
46 while (*p) {
47 if (*p == c) {
48 /* LINTED interface specification */
49 return (wchar_t *)p;
50 }
51 p++;
52 }
53 return NULL;
54}
diff --git a/src/lib/libc/string/wcscmp.c b/src/lib/libc/string/wcscmp.c
new file mode 100644
index 0000000000..0f0dc0efdf
--- /dev/null
+++ b/src/lib/libc/string/wcscmp.c
@@ -0,0 +1,56 @@
1/* $OpenBSD: wcscmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcscmp.c,v 1.5 2003/08/07 16:43:54 agc Exp $ */
3
4/*-
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: wcscmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <wchar.h>
41#include "locale/runetype.h"
42
43/*
44 * Compare strings.
45 */
46int
47wcscmp(s1, s2)
48 const wchar_t *s1, *s2;
49{
50
51 while (*s1 == *s2++)
52 if (*s1++ == 0)
53 return (0);
54 /* XXX assumes wchar_t = int */
55 return (*(const __nbrune_t *)s1 - *(const __nbrune_t *)--s2);
56}
diff --git a/src/lib/libc/string/wcscpy.c b/src/lib/libc/string/wcscpy.c
new file mode 100644
index 0000000000..266ea4a3df
--- /dev/null
+++ b/src/lib/libc/string/wcscpy.c
@@ -0,0 +1,53 @@
1/* $OpenBSD: wcscpy.c,v 1.2 2005/04/16 10:40:45 tom Exp $ */
2/* $NetBSD: wcscpy.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcscpy.c,v 1.2 2000/12/21 04:51:09 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcscpy.c,v 1.2 2005/04/16 10:40:45 tom Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcscpy(s1, s2)
40 wchar_t *s1;
41 const wchar_t *s2;
42{
43 wchar_t *p;
44 const wchar_t *q;
45
46 p = s1;
47 q = s2;
48 while (*q)
49 *p++ = *q++;
50 *p = '\0';
51
52 return s1;
53}
diff --git a/src/lib/libc/string/wcscspn.c b/src/lib/libc/string/wcscspn.c
new file mode 100644
index 0000000000..905c937695
--- /dev/null
+++ b/src/lib/libc/string/wcscspn.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: wcscspn.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcscspn.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcscspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcscspn.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38size_t
39wcscspn(s, set)
40 const wchar_t *s;
41 const wchar_t *set;
42{
43 const wchar_t *p;
44 const wchar_t *q;
45
46 p = s;
47 while (*p) {
48 q = set;
49 while (*q) {
50 if (*p == *q)
51 goto done;
52 q++;
53 }
54 p++;
55 }
56
57done:
58 return (p - s);
59}
diff --git a/src/lib/libc/string/wcslcat.c b/src/lib/libc/string/wcslcat.c
new file mode 100644
index 0000000000..266d012ad4
--- /dev/null
+++ b/src/lib/libc/string/wcslcat.c
@@ -0,0 +1,75 @@
1/* $OpenBSD: wcslcat.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcslcat.c,v 1.2 2001/01/03 14:33:02 lukem Exp $ */
3/* from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp */
4
5/*
6 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
7 * All rights reserved.
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. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcslcat.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <sys/types.h>
37#include <wchar.h>
38
39/*
40 * Appends src to string dst of size siz (unlike wcsncat, siz is the
41 * full size of dst, not space left). At most siz-1 characters
42 * will be copied. Always NUL terminates (unless siz == 0).
43 * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
44 * truncation occurred.
45 */
46size_t
47wcslcat(dst, src, siz)
48 wchar_t *dst;
49 const wchar_t *src;
50 size_t siz;
51{
52 wchar_t *d = dst;
53 const wchar_t *s = src;
54 size_t n = siz;
55 size_t dlen;
56
57 /* Find the end of dst and adjust bytes left but don't go past end */
58 while (*d != '\0' && n-- != 0)
59 d++;
60 dlen = d - dst;
61 n = siz - dlen;
62
63 if (n == 0)
64 return(dlen + wcslen(s));
65 while (*s != '\0') {
66 if (n != 1) {
67 *d++ = *s;
68 n--;
69 }
70 s++;
71 }
72 *d = '\0';
73
74 return(dlen + (s - src)); /* count does not include NUL */
75}
diff --git a/src/lib/libc/string/wcslcpy.c b/src/lib/libc/string/wcslcpy.c
new file mode 100644
index 0000000000..101161e9ce
--- /dev/null
+++ b/src/lib/libc/string/wcslcpy.c
@@ -0,0 +1,71 @@
1/* $OpenBSD: wcslcpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcslcpy.c,v 1.2 2001/01/03 14:33:02 lukem Exp $ */
3/* from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp */
4
5/*
6 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
7 * All rights reserved.
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. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcslcpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <sys/types.h>
37#include <wchar.h>
38
39/*
40 * Copy src to string dst of size siz. At most siz-1 characters
41 * will be copied. Always NUL terminates (unless siz == 0).
42 * Returns wcslen(src); if retval >= siz, truncation occurred.
43 */
44size_t
45wcslcpy(dst, src, siz)
46 wchar_t *dst;
47 const wchar_t *src;
48 size_t siz;
49{
50 wchar_t *d = dst;
51 const wchar_t *s = src;
52 size_t n = siz;
53
54 /* Copy as many bytes as will fit */
55 if (n != 0 && --n != 0) {
56 do {
57 if ((*d++ = *s++) == 0)
58 break;
59 } while (--n != 0);
60 }
61
62 /* Not enough room in dst, add NUL and traverse rest of src */
63 if (n == 0) {
64 if (siz != 0)
65 *d = '\0'; /* NUL-terminate dst */
66 while (*s++)
67 ;
68 }
69
70 return(s - src - 1); /* count does not include NUL */
71}
diff --git a/src/lib/libc/string/wcslen.c b/src/lib/libc/string/wcslen.c
new file mode 100644
index 0000000000..6d1c5e5f30
--- /dev/null
+++ b/src/lib/libc/string/wcslen.c
@@ -0,0 +1,49 @@
1/* $OpenBSD: wcslen.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcslen.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcslen.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcslen.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38size_t
39wcslen(s)
40 const wchar_t *s;
41{
42 const wchar_t *p;
43
44 p = s;
45 while (*p)
46 p++;
47
48 return p - s;
49}
diff --git a/src/lib/libc/string/wcsncat.c b/src/lib/libc/string/wcsncat.c
new file mode 100644
index 0000000000..984ef4cabb
--- /dev/null
+++ b/src/lib/libc/string/wcsncat.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: wcsncat.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsncat.c,v 1.2 2001/01/03 14:29:36 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcsncat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcsncat.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcsncat(s1, s2, n)
40 wchar_t *s1;
41 const wchar_t *s2;
42 size_t n;
43{
44 wchar_t *p;
45 wchar_t *q;
46 const wchar_t *r;
47
48 p = s1;
49 while (*p)
50 p++;
51 q = p;
52 r = s2;
53 while (*r && n) {
54 *q++ = *r++;
55 n--;
56 }
57 *q = '\0';
58 return s1;
59}
diff --git a/src/lib/libc/string/wcsncmp.c b/src/lib/libc/string/wcsncmp.c
new file mode 100644
index 0000000000..e89b7914d1
--- /dev/null
+++ b/src/lib/libc/string/wcsncmp.c
@@ -0,0 +1,58 @@
1/* $OpenBSD: wcsncmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsncmp.c,v 1.5 2003/08/07 16:43:54 agc Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: wcsncmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <wchar.h>
38#include "locale/runetype.h"
39
40int
41wcsncmp(s1, s2, n)
42 const wchar_t *s1, *s2;
43 size_t n;
44{
45
46 if (n == 0)
47 return (0);
48 do {
49 if (*s1 != *s2++) {
50 /* XXX assumes wchar_t = int */
51 return (*(const __nbrune_t *)s1 -
52 *(const __nbrune_t *)--s2);
53 }
54 if (*s1++ == 0)
55 break;
56 } while (--n != 0);
57 return (0);
58}
diff --git a/src/lib/libc/string/wcsncpy.c b/src/lib/libc/string/wcsncpy.c
new file mode 100644
index 0000000000..aa7bf95919
--- /dev/null
+++ b/src/lib/libc/string/wcsncpy.c
@@ -0,0 +1,57 @@
1/* $OpenBSD: wcsncpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsncpy.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcsncpy.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcsncpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcsncpy(s1, s2, n)
40 wchar_t *s1;
41 const wchar_t *s2;
42 size_t n;
43{
44 wchar_t *p;
45 const wchar_t *q;
46
47 *s1 = '\0';
48 p = s1;
49 q = s2;
50 while (n && *q) {
51 *p++ = *q++;
52 n--;
53 }
54 *p = '\0';
55
56 return s1;
57}
diff --git a/src/lib/libc/string/wcspbrk.c b/src/lib/libc/string/wcspbrk.c
new file mode 100644
index 0000000000..aeaac6ced4
--- /dev/null
+++ b/src/lib/libc/string/wcspbrk.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: wcspbrk.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcspbrk.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcspbrk.c,v 1.2 2000/12/21 05:07:25 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcspbrk.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcspbrk(s, set)
40 const wchar_t *s;
41 const wchar_t *set;
42{
43 const wchar_t *p;
44 const wchar_t *q;
45
46 p = s;
47 while (*p) {
48 q = set;
49 while (*q) {
50 if (*p == *q) {
51 /* LINTED interface specification */
52 return (wchar_t *)p;
53 }
54 q++;
55 }
56 p++;
57 }
58 return NULL;
59}
diff --git a/src/lib/libc/string/wcsrchr.c b/src/lib/libc/string/wcsrchr.c
new file mode 100644
index 0000000000..d0cd8aebb4
--- /dev/null
+++ b/src/lib/libc/string/wcsrchr.c
@@ -0,0 +1,56 @@
1/* $OpenBSD: wcsrchr.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsrchr.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcsrchr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcsrchr.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wcsrchr(s, c)
40 const wchar_t *s;
41 wchar_t c;
42{
43 const wchar_t *p;
44
45 p = s;
46 while (*p)
47 p++;
48 while (s <= p) {
49 if (*p == c) {
50 /* LINTED interface specification */
51 return (wchar_t *)p;
52 }
53 p--;
54 }
55 return NULL;
56}
diff --git a/src/lib/libc/string/wcsspn.c b/src/lib/libc/string/wcsspn.c
new file mode 100644
index 0000000000..52b22e3d3b
--- /dev/null
+++ b/src/lib/libc/string/wcsspn.c
@@ -0,0 +1,61 @@
1/* $OpenBSD: wcsspn.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsspn.c,v 1.3 2001/09/21 16:09:15 yamt Exp $ */
3
4/*-
5 * Copyright (c)1999,2001 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Citrus: xpg4dl/FreeBSD/lib/libc/string/wcsspn.c,v 1.3 2001/09/21 16:06:43 yamt Exp $
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcsspn.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38size_t
39wcsspn(s, set)
40 const wchar_t *s;
41 const wchar_t *set;
42{
43 const wchar_t *p;
44 const wchar_t *q;
45
46 p = s;
47 while (*p) {
48 q = set;
49 while (*q) {
50 if (*p == *q)
51 break;
52 q++;
53 }
54 if (!*q)
55 goto done;
56 p++;
57 }
58
59done:
60 return (p - s);
61}
diff --git a/src/lib/libc/string/wcsstr.c b/src/lib/libc/string/wcsstr.c
new file mode 100644
index 0000000000..992b5cab0f
--- /dev/null
+++ b/src/lib/libc/string/wcsstr.c
@@ -0,0 +1,76 @@
1/* $OpenBSD: wcsstr.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcsstr.c,v 1.3 2003/03/05 20:18:17 tshiozak Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcsstr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcsstr.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39#ifdef WCSWCS
40wcswcs(big, little)
41#else
42wcsstr(big, little)
43#endif
44 const wchar_t *big;
45 const wchar_t *little;
46{
47 const wchar_t *p;
48 const wchar_t *q;
49 const wchar_t *r;
50
51 if (!*little) {
52 /* LINTED interface specification */
53 return (wchar_t *)big;
54 }
55 if (wcslen(big) < wcslen(little))
56 return NULL;
57
58 p = big;
59 q = little;
60 while (*p) {
61 q = little;
62 r = p;
63 while (*q) {
64 if (*r != *q)
65 break;
66 q++;
67 r++;
68 }
69 if (!*q) {
70 /* LINTED interface specification */
71 return (wchar_t *)p;
72 }
73 p++;
74 }
75 return NULL;
76}
diff --git a/src/lib/libc/string/wcstok.3 b/src/lib/libc/string/wcstok.3
new file mode 100644
index 0000000000..dd3f36cfd5
--- /dev/null
+++ b/src/lib/libc/string/wcstok.3
@@ -0,0 +1,136 @@
1.\" $OpenBSD: wcstok.3,v 1.2 2005/04/13 20:42:48 jmc Exp $
2.\"
3.\" $NetBSD: wcstok.3,v 1.3 2003/09/08 17:54:33 wiz Exp $
4.\"
5.\" Copyright (c) 1998 Softweyr LLC. All rights reserved.
6.\"
7.\" strtok_r, from Berkeley strtok
8.\" Oct 13, 1998 by Wes Peters <wes@softweyr.com>
9.\"
10.\" Copyright (c) 1988, 1991, 1993
11.\" The Regents of the University of California. All rights reserved.
12.\"
13.\" This code is derived from software contributed to Berkeley by
14.\" the American National Standards Committee X3, on Information
15.\" Processing Systems.
16.\"
17.\" Redistribution and use in source and binary forms, with or without
18.\" modification, are permitted provided that the following conditions
19.\" are met:
20.\"
21.\" 1. Redistributions of source code must retain the above copyright
22.\" notices, this list of conditions and the following disclaimer.
23.\"
24.\" 2. Redistributions in binary form must reproduce the above
25.\" copyright notices, this list of conditions and the following
26.\" disclaimer in the documentation and/or other materials provided
27.\" with the distribution.
28.\"
29.\" 3. All advertising materials mentioning features or use of this
30.\" software must display the following acknowledgement:
31.\"
32.\" This product includes software developed by Softweyr LLC, the
33.\" University of California, Berkeley, and its contributors.
34.\"
35.\" 4. Neither the name of Softweyr LLC, the University nor the names
36.\" of its contributors may be used to endorse or promote products
37.\" derived from this software without specific prior written
38.\" permission.
39.\"
40.\" THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND
41.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
42.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44.\" DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE REGENTS, OR
45.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52.\" SUCH DAMAGE.
53.\"
54.\" Original version ID:
55.\" FreeBSD: src/lib/libc/string/wcstok.3,v 1.4 2002/10/15 09:49:54 tjr Exp
56.\"
57.Dd October 3, 2002
58.Dt WCSTOK 3
59.Os
60.Sh NAME
61.Nm wcstok
62.Nd split wide-character string into tokens
63.Sh SYNOPSIS
64.In wchar.h
65.Ft wchar_t *
66.Fn wcstok "wchar_t * restrict str" "const wchar_t * restrict sep" "wchar_t ** restrict last"
67.Sh DESCRIPTION
68The
69.Fn wcstok
70function
71is used to isolate sequential tokens in a null-terminated wide character
72string,
73.Fa str .
74These tokens are separated in the string by at least one of the
75characters in
76.Fa sep .
77The first time that
78.Fn wcstok
79is called,
80.Fa str
81should be specified; subsequent calls, wishing to obtain further tokens
82from the same string, should pass a null pointer instead.
83The separator string,
84.Fa sep ,
85must be supplied each time, and may change between calls.
86The context pointer
87.Fa last
88must be provided on each call.
89.Pp
90The
91.Fn wcstok
92function is the wide character counterpart of the
93.Fn strtok_r
94function.
95.Sh RETURN VALUES
96The
97.Fn wcstok
98function
99returns a pointer to the beginning of each subsequent token in the string,
100after replacing the token itself with a null wide character (L'\e0').
101When no more tokens remain, a null pointer is returned.
102.Sh EXAMPLES
103The following code fragment splits a wide character string on
104.Tn ASCII
105space, tab and newline characters and writes the tokens to
106standard output:
107.Bd -literal -offset indent
108const wchar_t *seps = L" \et\en";
109wchar_t *last, *tok, text[] = L" \enone\ettwo\et\etthree \en";
110
111for (tok = wcstok(text, seps, &last); tok != NULL;
112 tok = wcstok(NULL, seps, &last))
113 wprintf(L"%ls\en", tok);
114.Ed
115.Sh COMPATIBILITY
116Some early implementations of
117.Fn wcstok
118omit the
119context pointer argument,
120.Fa last ,
121and maintain state across calls in a static variable like
122.Fn strtok
123does.
124.Sh SEE ALSO
125.Xr strtok 3 ,
126.Xr wcschr 3 ,
127.Xr wcscspn 3 ,
128.Xr wcspbrk 3 ,
129.Xr wcsrchr 3 ,
130.Xr wcsspn 3
131.Sh STANDARDS
132The
133.Fn wcstok
134function
135conforms to
136.St -isoC-99 .
diff --git a/src/lib/libc/string/wcstok.c b/src/lib/libc/string/wcstok.c
new file mode 100644
index 0000000000..1b0790fdc6
--- /dev/null
+++ b/src/lib/libc/string/wcstok.c
@@ -0,0 +1,99 @@
1/* $OpenBSD: wcstok.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcstok.c,v 1.3 2003/07/10 08:50:48 tshiozak Exp $ */
3
4/*-
5 * Copyright (c) 1998 Softweyr LLC. All rights reserved.
6 *
7 * strtok_r, from Berkeley strtok
8 * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
9 *
10 * Copyright (c) 1988, 1993
11 * The Regents of the University of California. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notices, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notices, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Softweyr LLC, the
24 * University of California, Berkeley, and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
32 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
33 * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
35 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Original version ID:
42 * FreeBSD: src/lib/libc/string/wcstok.c,v 1.1 2002/09/07 08:16:57 tjr Exp
43 */
44
45#if defined(LIBC_SCCS) && !defined(lint)
46static char *rcsid = "$OpenBSD: wcstok.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
47#endif /* LIBC_SCCS and not lint */
48
49#include <wchar.h>
50
51wchar_t *
52wcstok(s, delim, last)
53 wchar_t * __restrict s;
54 const wchar_t * __restrict delim;
55 wchar_t ** __restrict last;
56{
57 const wchar_t *spanp;
58 wchar_t c, sc;
59 wchar_t *tok;
60
61 if (s == NULL && (s = *last) == NULL)
62 return (NULL);
63
64 /*
65 * Skip (span) leading delimiters (s += wcsspn(s, delim), sort of).
66 */
67cont:
68 c = *s++;
69 for (spanp = delim; (sc = *spanp++) != L'\0';) {
70 if (c == sc)
71 goto cont;
72 }
73
74 if (c == L'\0') { /* no non-delimiter characters */
75 *last = NULL;
76 return (NULL);
77 }
78 tok = s - 1;
79
80 /*
81 * Scan token (scan for delimiters: s += wcscspn(s, delim), sort of).
82 * Note that delim must have one NUL; we stop if we see that, too.
83 */
84 for (;;) {
85 c = *s++;
86 spanp = delim;
87 do {
88 if ((sc = *spanp++) == c) {
89 if (c == L'\0')
90 s = NULL;
91 else
92 s[-1] = L'\0';
93 *last = s;
94 return (tok);
95 }
96 } while (sc != L'\0');
97 }
98 /* NOTREACHED */
99}
diff --git a/src/lib/libc/string/wcswcs.c b/src/lib/libc/string/wcswcs.c
new file mode 100644
index 0000000000..bd35605547
--- /dev/null
+++ b/src/lib/libc/string/wcswcs.c
@@ -0,0 +1,5 @@
1/* $OpenBSD: wcswcs.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcswcs.c,v 1.1 2003/03/05 20:18:17 tshiozak Exp $ */
3
4#define WCSWCS
5#include "wcsstr.c"
diff --git a/src/lib/libc/string/wcswidth.c b/src/lib/libc/string/wcswidth.c
new file mode 100644
index 0000000000..c55d9ae72a
--- /dev/null
+++ b/src/lib/libc/string/wcswidth.c
@@ -0,0 +1,53 @@
1/* $OpenBSD: wcswidth.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wcswidth.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wcswidth.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wcswidth.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38int
39wcswidth(s, n)
40 const wchar_t *s;
41 size_t n;
42{
43 int w;
44
45 w = 0;
46 while (n && *s) {
47 w += wcwidth(*s);
48 s++;
49 n--;
50 }
51
52 return w;
53}
diff --git a/src/lib/libc/string/wmemchr.3 b/src/lib/libc/string/wmemchr.3
new file mode 100644
index 0000000000..0b6935837c
--- /dev/null
+++ b/src/lib/libc/string/wmemchr.3
@@ -0,0 +1,141 @@
1.\" $OpenBSD: wmemchr.3,v 1.2 2005/04/13 20:42:48 jmc Exp $
2.\"
3.\" $NetBSD: wmemchr.3,v 1.9 2003/09/08 17:54:33 wiz Exp $
4.\"
5.\" Copyright (c) 1990, 1991, 1993
6.\" The Regents of the University of California. All rights reserved.
7.\"
8.\" This code is derived from software contributed to Berkeley by
9.\" Chris Torek and the American National Standards Committee X3,
10.\" on Information Processing Systems.
11.\"
12.\" Redistribution and use in source and binary forms, with or without
13.\" modification, are permitted provided that the following conditions
14.\" are met:
15.\" 1. Redistributions of source code must retain the above copyright
16.\" notice, this list of conditions and the following disclaimer.
17.\" 2. Redistributions in binary form must reproduce the above copyright
18.\" notice, this list of conditions and the following disclaimer in the
19.\" documentation and/or other materials provided with the distribution.
20.\" 3. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission.
23.\"
24.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE.
35.\"
36.\" from: @(#)strcpy.3 8.1 (Berkeley) 6/4/93
37.\"
38.Dd December 22, 2000
39.Dt WMEMCHR 3
40.Os
41.Sh NAME
42.Nm wmemchr ,
43.Nm wmemcmp ,
44.Nm wmemcpy ,
45.Nm wmemmove ,
46.Nm wmemset ,
47.Nm wcscat ,
48.Nm wcschr ,
49.Nm wcscmp ,
50.Nm wcscpy ,
51.Nm wcscspn ,
52.Nm wcslcat ,
53.Nm wcslcpy ,
54.Nm wcslen ,
55.Nm wcsncat ,
56.Nm wcsncmp ,
57.Nm wcsncpy ,
58.Nm wcspbrk ,
59.Nm wcsrchr ,
60.Nm wcsspn ,
61.Nm wcsstr
62.Nd wide character string manipulation operations
63.Sh SYNOPSIS
64.In wchar.h
65.Ft wchar_t *
66.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n"
67.Ft int
68.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
69.Ft wchar_t *
70.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
71.Ft wchar_t *
72.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n"
73.Ft wchar_t *
74.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
75.Ft wchar_t *
76.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
77.Ft wchar_t *
78.Fn wcschr "const wchar_t *s" "wchar_t c"
79.Ft int
80.Fn wcscmp "const wchar_t *s1" "const wchar_t *s2"
81.Ft wchar_t *
82.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2"
83.Ft size_t
84.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2"
85.Ft size_t
86.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
87.Ft size_t
88.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
89.Ft size_t
90.Fn wcslen "const wchar_t *s"
91.Ft wchar_t *
92.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
93.Ft int
94.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
95.Ft wchar_t *
96.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
97.Ft wchar_t *
98.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
99.Ft wchar_t *
100.Fn wcsrchr "const wchar_t *s" "wchar_t c"
101.Ft size_t
102.Fn wcsspn "const wchar_t *s1" "const wchar_t *s2"
103.Ft wchar_t *
104.Fn wcsstr "const wchar_t *s1" "const wchar_t *s2"
105.Sh DESCRIPTION
106These functions implement string manipulation operations over wide character
107strings.
108For a detailed description, refer to documents for the respective single-byte
109counterpart, such as
110.Xr memchr 3 .
111.Sh SEE ALSO
112.Xr memchr 3 ,
113.Xr memcmp 3 ,
114.Xr memcpy 3 ,
115.Xr memmove 3 ,
116.Xr memset 3 ,
117.Xr strcat 3 ,
118.Xr strchr 3 ,
119.Xr strcmp 3 ,
120.Xr strcpy 3 ,
121.Xr strcspn 3 ,
122.Xr strlcat 3 ,
123.Xr strlcpy 3 ,
124.Xr strlen 3 ,
125.Xr strncat 3 ,
126.Xr strncmp 3 ,
127.Xr strncpy 3 ,
128.Xr strpbrk 3 ,
129.Xr strrchr 3 ,
130.Xr strspn 3 ,
131.Xr strstr 3
132.Sh STANDARDS
133These functions conform to
134.St -isoC-99
135and were first introduced in
136.St -isoC-amd1 ,
137with the exception of
138.Fn wcslcat
139and
140.Fn wcslcpy ,
141which are extensions.
diff --git a/src/lib/libc/string/wmemchr.c b/src/lib/libc/string/wmemchr.c
new file mode 100644
index 0000000000..0e50205863
--- /dev/null
+++ b/src/lib/libc/string/wmemchr.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: wmemchr.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wmemchr.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wmemchr.c,v 1.2 2000/12/20 14:08:31 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wmemchr.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wmemchr(s, c, n)
40 const wchar_t *s;
41 wchar_t c;
42 size_t n;
43{
44 size_t i;
45
46 for (i = 0; i < n; i++) {
47 if (*s == c) {
48 /* LINTED const castaway */
49 return (wchar_t *)s;
50 }
51 s++;
52 }
53 return NULL;
54}
diff --git a/src/lib/libc/string/wmemcmp.c b/src/lib/libc/string/wmemcmp.c
new file mode 100644
index 0000000000..4792a3b456
--- /dev/null
+++ b/src/lib/libc/string/wmemcmp.c
@@ -0,0 +1,57 @@
1/* $OpenBSD: wmemcmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wmemcmp.c,v 1.3 2003/04/06 18:33:23 tshiozak Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wmemcmp.c,v 1.2 2000/12/20 14:08:31 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wmemcmp.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37#include "locale/runetype.h"
38
39int
40wmemcmp(s1, s2, n)
41 const wchar_t *s1;
42 const wchar_t *s2;
43 size_t n;
44{
45 size_t i;
46
47 for (i = 0; i < n; i++) {
48 if (*s1 != *s2) {
49 /* wchar might be unsigned */
50 return *(const __nbrune_t *)s1 >
51 *(const __nbrune_t *)s2 ? 1 : -1;
52 }
53 s1++;
54 s2++;
55 }
56 return 0;
57}
diff --git a/src/lib/libc/string/wmemcpy.c b/src/lib/libc/string/wmemcpy.c
new file mode 100644
index 0000000000..628795ce41
--- /dev/null
+++ b/src/lib/libc/string/wmemcpy.c
@@ -0,0 +1,47 @@
1/* $OpenBSD: wmemcpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wmemcpy.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wmemcpy.c,v 1.2 2000/12/20 14:08:31 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wmemcpy.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <string.h>
37#include <wchar.h>
38
39wchar_t *
40wmemcpy(d, s, n)
41 wchar_t *d;
42 const wchar_t *s;
43 size_t n;
44{
45
46 return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
47}
diff --git a/src/lib/libc/string/wmemmove.c b/src/lib/libc/string/wmemmove.c
new file mode 100644
index 0000000000..e5a0a1fe25
--- /dev/null
+++ b/src/lib/libc/string/wmemmove.c
@@ -0,0 +1,47 @@
1/* $OpenBSD: wmemmove.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wmemmove.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wmemmove.c,v 1.2 2000/12/20 14:08:31 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wmemmove.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <string.h>
37#include <wchar.h>
38
39wchar_t *
40wmemmove(d, s, n)
41 wchar_t *d;
42 const wchar_t *s;
43 size_t n;
44{
45
46 return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
47}
diff --git a/src/lib/libc/string/wmemset.c b/src/lib/libc/string/wmemset.c
new file mode 100644
index 0000000000..abcbe44c46
--- /dev/null
+++ b/src/lib/libc/string/wmemset.c
@@ -0,0 +1,53 @@
1/* $OpenBSD: wmemset.c,v 1.1 2005/04/13 16:35:58 espie Exp $ */
2/* $NetBSD: wmemset.c,v 1.2 2001/01/03 14:29:37 lukem Exp $ */
3
4/*-
5 * Copyright (c)1999 Citrus Project,
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * citrus Id: wmemset.c,v 1.2 2000/12/20 14:08:31 itojun Exp
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *rcsid = "$OpenBSD: wmemset.c,v 1.1 2005/04/13 16:35:58 espie Exp $";
34#endif /* LIBC_SCCS and not lint */
35
36#include <wchar.h>
37
38wchar_t *
39wmemset(s, c, n)
40 wchar_t *s;
41 wchar_t c;
42 size_t n;
43{
44 size_t i;
45 wchar_t *p;
46
47 p = (wchar_t *)s;
48 for (i = 0; i < n; i++) {
49 *p = c;
50 p++;
51 }
52 return s;
53}